api_submission_tests.html

Report generated on 22-Sep-2025 at 14:58:45 by pytest-html v3.1.1

Summary

60 tests ran in 440.55 seconds.

21 passed, 2 skipped, 39 failed, 2 errors, 0 expected failures, 0 unexpected passes, 0 rerun

Results

Result Test Duration Links
Error tests/api_w/test_addon_uploads.py::test_upload_privileged_addon_with_authorized_account[Desktop]::setup 4.39
selenium = <selenium.webdriver.firefox.webdriver.WebDriver (session="cc15d608-012d-4cb1-834f-5c7eedf8af52")>, base_url = 'https://addons.allizom.org', session_auth = None
request = <SubRequest 'selenium' for <Function test_upload_privileged_addon_with_authorized_account[Desktop]>>

@pytest.fixture(
scope="function",
params=[DESKTOP],
ids=["Desktop"],
)
def selenium(selenium, base_url, session_auth, request):
"""Fixture to set a custom resolution for tests running on Desktop
and handle browser sessions when needed"""
selenium.set_window_size(*request.param)
# establishing actions based on markers
create_session = request.node.get_closest_marker("create_session")
login = request.node.get_closest_marker("login")
clear_session = request.node.get_closest_marker("clear_session")
# this is used when we want to open an AMO page with a sessionid
# cookie (i.e. a logged-in user) already set
if create_session:
# need to set the url context if we want to apply a cookie
# in order to avoid InvalidCookieDomainException error
selenium.get(base_url)
# set the sessionid cookie
selenium.add_cookie(
{
"name": "sessionid",
"value": session_auth,
}
)
# this is used when we want to start the browser with a normal login
# mostly used for the scope of getting the session cookie and storing it for later use
if login:
> home = Home(selenium, base_url).open().wait_for_page_to_load()

tests/conftest.py:127:
_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _
venv/lib/python3.11/site-packages/pypom/page.py:130: in open
self.driver_adapter.open(self.seed_url)
venv/lib/python3.11/site-packages/pypom/selenium_driver.py:44: in open
self.driver.get(url)
venv/lib/python3.11/site-packages/selenium/webdriver/remote/webdriver.py:441: in get
self.execute(Command.GET, {'url': url})
venv/lib/python3.11/site-packages/selenium/webdriver/remote/webdriver.py:429: in execute
self.error_handler.check_response(response)
_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _

self = <selenium.webdriver.remote.errorhandler.ErrorHandler object at 0x104ba0b50>
response = {'status': 500, 'value': '{"value":{"error":"unknown error","message":"Reached error page: about:neterror?e=dnsNotFoun....sys.mjs:156:19\\nreceiveMessage@chrome://remote/content/marionette/actors/MarionetteEventsParent.sys.mjs:33:25\\n"}}'}

def check_response(self, response: Dict[str, Any]) -> None:
"""
Checks that a JSON response from the WebDriver does not have an error.

:Args:
- response - The JSON response from the WebDriver server as a dictionary
object.

:Raises: If the response contains an error message.
"""
status = response.get('status', None)
if not status or status == ErrorCode.SUCCESS:
return
value = None
message = response.get("message", "")
screen: str = response.get("screen", "")
stacktrace = None
if isinstance(status, int):
value_json = response.get('value', None)
if value_json and isinstance(value_json, str):
import json
try:
value = json.loads(value_json)
if len(value.keys()) == 1:
value = value['value']
status = value.get('error', None)
if not status:
status = value.get("status", ErrorCode.UNKNOWN_ERROR)
message = value.get("value") or value.get("message")
if not isinstance(message, str):
value = message
message = message.get('message')
else:
message = value.get('message', None)
except ValueError:
pass

exception_class: Type[WebDriverException]
if status in ErrorCode.NO_SUCH_ELEMENT:
exception_class = NoSuchElementException
elif status in ErrorCode.NO_SUCH_FRAME:
exception_class = NoSuchFrameException
elif status in ErrorCode.NO_SUCH_SHADOW_ROOT:
exception_class = NoSuchShadowRootException
elif status in ErrorCode.NO_SUCH_WINDOW:
exception_class = NoSuchWindowException
elif status in ErrorCode.STALE_ELEMENT_REFERENCE:
exception_class = StaleElementReferenceException
elif status in ErrorCode.ELEMENT_NOT_VISIBLE:
exception_class = ElementNotVisibleException
elif status in ErrorCode.INVALID_ELEMENT_STATE:
exception_class = InvalidElementStateException
elif status in ErrorCode.INVALID_SELECTOR \
or status in ErrorCode.INVALID_XPATH_SELECTOR \
or status in ErrorCode.INVALID_XPATH_SELECTOR_RETURN_TYPER:
exception_class = InvalidSelectorException
elif status in ErrorCode.ELEMENT_IS_NOT_SELECTABLE:
exception_class = ElementNotSelectableException
elif status in ErrorCode.ELEMENT_NOT_INTERACTABLE:
exception_class = ElementNotInteractableException
elif status in ErrorCode.INVALID_COOKIE_DOMAIN:
exception_class = InvalidCookieDomainException
elif status in ErrorCode.UNABLE_TO_SET_COOKIE:
exception_class = UnableToSetCookieException
elif status in ErrorCode.TIMEOUT:
exception_class = TimeoutException
elif status in ErrorCode.SCRIPT_TIMEOUT:
exception_class = TimeoutException
elif status in ErrorCode.UNKNOWN_ERROR:
exception_class = WebDriverException
elif status in ErrorCode.UNEXPECTED_ALERT_OPEN:
exception_class = UnexpectedAlertPresentException
elif status in ErrorCode.NO_ALERT_OPEN:
exception_class = NoAlertPresentException
elif status in ErrorCode.IME_NOT_AVAILABLE:
exception_class = ImeNotAvailableException
elif status in ErrorCode.IME_ENGINE_ACTIVATION_FAILED:
exception_class = ImeActivationFailedException
elif status in ErrorCode.MOVE_TARGET_OUT_OF_BOUNDS:
exception_class = MoveTargetOutOfBoundsException
elif status in ErrorCode.JAVASCRIPT_ERROR:
exception_class = JavascriptException
elif status in ErrorCode.SESSION_NOT_CREATED:
exception_class = SessionNotCreatedException
elif status in ErrorCode.INVALID_ARGUMENT:
exception_class = InvalidArgumentException
elif status in ErrorCode.NO_SUCH_COOKIE:
exception_class = NoSuchCookieException
elif status in ErrorCode.UNABLE_TO_CAPTURE_SCREEN:
exception_class = ScreenshotException
elif status in ErrorCode.ELEMENT_CLICK_INTERCEPTED:
exception_class = ElementClickInterceptedException
elif status in ErrorCode.INSECURE_CERTIFICATE:
exception_class = InsecureCertificateException
elif status in ErrorCode.INVALID_COORDINATES:
exception_class = InvalidCoordinatesException
elif status in ErrorCode.INVALID_SESSION_ID:
exception_class = InvalidSessionIdException
elif status in ErrorCode.UNKNOWN_METHOD:
exception_class = UnknownMethodException
else:
exception_class = WebDriverException
if not value:
value = response['value']
if isinstance(value, str):
raise exception_class(value)
if message == "" and 'message' in value:
message = value['message']

screen = None # type: ignore[assignment]
if 'screen' in value:
screen = value['screen']

stacktrace = None
st_value = value.get('stackTrace') or value.get('stacktrace')
if st_value:
if isinstance(st_value, str):
stacktrace = st_value.split('\n')
else:
stacktrace = []
try:
for frame in st_value:
line = frame.get("lineNumber", "")
file = frame.get("fileName", "<anonymous>")
if line:
file = f"{file}:{line}"
meth = frame.get('methodName', '<anonymous>')
if 'className' in frame:
meth = "{}.{}".format(frame['className'], meth)
msg = " at %s (%s)"
msg = msg % (meth, file)
stacktrace.append(msg)
except TypeError:
pass
if exception_class == UnexpectedAlertPresentException:
alert_text = None
if 'data' in value:
alert_text = value['data'].get('text')
elif 'alert' in value:
alert_text = value['alert'].get('text')
raise exception_class(message, screen, stacktrace, alert_text) # type: ignore[call-arg] # mypy is not smart enough here
> raise exception_class(message, screen, stacktrace)
E selenium.common.exceptions.WebDriverException: Message: Reached error page: about:neterror?e=dnsNotFound&u=https%3A//addons.allizom.org/&c=UTF-8&d=We%20can%E2%80%99t%20connect%20to%20the%20server%20at%20addons.allizom.org.
E Stacktrace:
E RemoteError@chrome://remote/content/shared/RemoteError.sys.mjs:8:8
E WebDriverError@chrome://remote/content/shared/webdriver/Errors.sys.mjs:202:5
E UnknownError@chrome://remote/content/shared/webdriver/Errors.sys.mjs:961:5
E checkReadyState@chrome://remote/content/marionette/navigate.sys.mjs:59:24
E onNavigation@chrome://remote/content/marionette/navigate.sys.mjs:348:39
E emit@resource://gre/modules/EventEmitter.sys.mjs:156:19
E receiveMessage@chrome://remote/content/marionette/actors/MarionetteEventsParent.sys.mjs:33:25

venv/lib/python3.11/site-packages/selenium/webdriver/remote/errorhandler.py:243: WebDriverException
Error tests/api_w/test_addon_uploads.py::test_upload_addon_with_trademark_name_authorized_account[Desktop]::setup 4.33
selenium = <selenium.webdriver.firefox.webdriver.WebDriver (session="ad8f50b0-afb0-42f9-8f5f-45c0ffab9d6d")>, base_url = 'https://addons.allizom.org', session_auth = 'km4duy1yzlp6bduifqwjbrl8biyyxblf'
request = <SubRequest 'selenium' for <Function test_upload_addon_with_trademark_name_authorized_account[Desktop]>>

@pytest.fixture(
scope="function",
params=[DESKTOP],
ids=["Desktop"],
)
def selenium(selenium, base_url, session_auth, request):
"""Fixture to set a custom resolution for tests running on Desktop
and handle browser sessions when needed"""
selenium.set_window_size(*request.param)
# establishing actions based on markers
create_session = request.node.get_closest_marker("create_session")
login = request.node.get_closest_marker("login")
clear_session = request.node.get_closest_marker("clear_session")
# this is used when we want to open an AMO page with a sessionid
# cookie (i.e. a logged-in user) already set
if create_session:
# need to set the url context if we want to apply a cookie
# in order to avoid InvalidCookieDomainException error
> selenium.get(base_url)

tests/conftest.py:116:
_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _
venv/lib/python3.11/site-packages/selenium/webdriver/remote/webdriver.py:441: in get
self.execute(Command.GET, {'url': url})
venv/lib/python3.11/site-packages/selenium/webdriver/remote/webdriver.py:429: in execute
self.error_handler.check_response(response)
_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _

self = <selenium.webdriver.remote.errorhandler.ErrorHandler object at 0x103f2a110>
response = {'status': 500, 'value': '{"value":{"error":"unknown error","message":"Reached error page: about:neterror?e=dnsNotFoun....sys.mjs:156:19\\nreceiveMessage@chrome://remote/content/marionette/actors/MarionetteEventsParent.sys.mjs:33:25\\n"}}'}

def check_response(self, response: Dict[str, Any]) -> None:
"""
Checks that a JSON response from the WebDriver does not have an error.

:Args:
- response - The JSON response from the WebDriver server as a dictionary
object.

:Raises: If the response contains an error message.
"""
status = response.get('status', None)
if not status or status == ErrorCode.SUCCESS:
return
value = None
message = response.get("message", "")
screen: str = response.get("screen", "")
stacktrace = None
if isinstance(status, int):
value_json = response.get('value', None)
if value_json and isinstance(value_json, str):
import json
try:
value = json.loads(value_json)
if len(value.keys()) == 1:
value = value['value']
status = value.get('error', None)
if not status:
status = value.get("status", ErrorCode.UNKNOWN_ERROR)
message = value.get("value") or value.get("message")
if not isinstance(message, str):
value = message
message = message.get('message')
else:
message = value.get('message', None)
except ValueError:
pass

exception_class: Type[WebDriverException]
if status in ErrorCode.NO_SUCH_ELEMENT:
exception_class = NoSuchElementException
elif status in ErrorCode.NO_SUCH_FRAME:
exception_class = NoSuchFrameException
elif status in ErrorCode.NO_SUCH_SHADOW_ROOT:
exception_class = NoSuchShadowRootException
elif status in ErrorCode.NO_SUCH_WINDOW:
exception_class = NoSuchWindowException
elif status in ErrorCode.STALE_ELEMENT_REFERENCE:
exception_class = StaleElementReferenceException
elif status in ErrorCode.ELEMENT_NOT_VISIBLE:
exception_class = ElementNotVisibleException
elif status in ErrorCode.INVALID_ELEMENT_STATE:
exception_class = InvalidElementStateException
elif status in ErrorCode.INVALID_SELECTOR \
or status in ErrorCode.INVALID_XPATH_SELECTOR \
or status in ErrorCode.INVALID_XPATH_SELECTOR_RETURN_TYPER:
exception_class = InvalidSelectorException
elif status in ErrorCode.ELEMENT_IS_NOT_SELECTABLE:
exception_class = ElementNotSelectableException
elif status in ErrorCode.ELEMENT_NOT_INTERACTABLE:
exception_class = ElementNotInteractableException
elif status in ErrorCode.INVALID_COOKIE_DOMAIN:
exception_class = InvalidCookieDomainException
elif status in ErrorCode.UNABLE_TO_SET_COOKIE:
exception_class = UnableToSetCookieException
elif status in ErrorCode.TIMEOUT:
exception_class = TimeoutException
elif status in ErrorCode.SCRIPT_TIMEOUT:
exception_class = TimeoutException
elif status in ErrorCode.UNKNOWN_ERROR:
exception_class = WebDriverException
elif status in ErrorCode.UNEXPECTED_ALERT_OPEN:
exception_class = UnexpectedAlertPresentException
elif status in ErrorCode.NO_ALERT_OPEN:
exception_class = NoAlertPresentException
elif status in ErrorCode.IME_NOT_AVAILABLE:
exception_class = ImeNotAvailableException
elif status in ErrorCode.IME_ENGINE_ACTIVATION_FAILED:
exception_class = ImeActivationFailedException
elif status in ErrorCode.MOVE_TARGET_OUT_OF_BOUNDS:
exception_class = MoveTargetOutOfBoundsException
elif status in ErrorCode.JAVASCRIPT_ERROR:
exception_class = JavascriptException
elif status in ErrorCode.SESSION_NOT_CREATED:
exception_class = SessionNotCreatedException
elif status in ErrorCode.INVALID_ARGUMENT:
exception_class = InvalidArgumentException
elif status in ErrorCode.NO_SUCH_COOKIE:
exception_class = NoSuchCookieException
elif status in ErrorCode.UNABLE_TO_CAPTURE_SCREEN:
exception_class = ScreenshotException
elif status in ErrorCode.ELEMENT_CLICK_INTERCEPTED:
exception_class = ElementClickInterceptedException
elif status in ErrorCode.INSECURE_CERTIFICATE:
exception_class = InsecureCertificateException
elif status in ErrorCode.INVALID_COORDINATES:
exception_class = InvalidCoordinatesException
elif status in ErrorCode.INVALID_SESSION_ID:
exception_class = InvalidSessionIdException
elif status in ErrorCode.UNKNOWN_METHOD:
exception_class = UnknownMethodException
else:
exception_class = WebDriverException
if not value:
value = response['value']
if isinstance(value, str):
raise exception_class(value)
if message == "" and 'message' in value:
message = value['message']

screen = None # type: ignore[assignment]
if 'screen' in value:
screen = value['screen']

stacktrace = None
st_value = value.get('stackTrace') or value.get('stacktrace')
if st_value:
if isinstance(st_value, str):
stacktrace = st_value.split('\n')
else:
stacktrace = []
try:
for frame in st_value:
line = frame.get("lineNumber", "")
file = frame.get("fileName", "<anonymous>")
if line:
file = f"{file}:{line}"
meth = frame.get('methodName', '<anonymous>')
if 'className' in frame:
meth = "{}.{}".format(frame['className'], meth)
msg = " at %s (%s)"
msg = msg % (meth, file)
stacktrace.append(msg)
except TypeError:
pass
if exception_class == UnexpectedAlertPresentException:
alert_text = None
if 'data' in value:
alert_text = value['data'].get('text')
elif 'alert' in value:
alert_text = value['alert'].get('text')
raise exception_class(message, screen, stacktrace, alert_text) # type: ignore[call-arg] # mypy is not smart enough here
> raise exception_class(message, screen, stacktrace)
E selenium.common.exceptions.WebDriverException: Message: Reached error page: about:neterror?e=dnsNotFound&u=https%3A//addons.allizom.org/&c=UTF-8&d=We%20can%E2%80%99t%20connect%20to%20the%20server%20at%20addons.allizom.org.
E Stacktrace:
E RemoteError@chrome://remote/content/shared/RemoteError.sys.mjs:8:8
E WebDriverError@chrome://remote/content/shared/webdriver/Errors.sys.mjs:202:5
E UnknownError@chrome://remote/content/shared/webdriver/Errors.sys.mjs:961:5
E checkReadyState@chrome://remote/content/marionette/navigate.sys.mjs:59:24
E onNavigation@chrome://remote/content/marionette/navigate.sys.mjs:348:39
E emit@resource://gre/modules/EventEmitter.sys.mjs:156:19
E receiveMessage@chrome://remote/content/marionette/actors/MarionetteEventsParent.sys.mjs:33:25

venv/lib/python3.11/site-packages/selenium/webdriver/remote/errorhandler.py:243: WebDriverException
Failed tests/api_w/test_addon_uploads.py::test_upload_addon_crx_archive 13.57
base_url = 'https://addons.allizom.org', session_auth = 'ldvd5ag27bkfpukx6rn2lcj0yuvakt3v'

@pytest.mark.serial
@pytest.mark.create_session("api_user")
def test_upload_addon_crx_archive(base_url, session_auth):
"""Use a .crx file to upload an addon and make sure the submission is successful"""
with open("sample-addons/crx_ext.crx", "rb") as file:
upload = requests.post(
url=f"{base_url}{_upload}",
headers={"Authorization": f"Session {session_auth}"},
files={"upload": file},
data={"channel": "unlisted"},
)
print(f"Session Token: {session_auth}")
print(f"Uploading to: {base_url}{_upload}")
time.sleep(5)
upload.raise_for_status()
uuid = upload.json()["uuid"]
payload = payloads.listed_addon_minimal(uuid)
create_addon = requests.post(
url=f"{base_url}{_addon_create}",
headers={
"Authorization": f"Session {session_auth}",
"Content-Type": "application/json",
},
data=json.dumps(payload),
)
time.sleep(5)
> create_addon.raise_for_status()

tests/api_w/test_addon_uploads.py:105:
_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _

self = <Response [400]>

def raise_for_status(self):
"""Raises :class:`HTTPError`, if one occurred."""

http_error_msg = ""
if isinstance(self.reason, bytes):
# We attempt to decode utf-8 first because some servers
# choose to localize their reason strings. If the string
# isn't utf-8, we fall back to iso-8859-1 for all other
# encodings. (See PR #3538)
try:
reason = self.reason.decode("utf-8")
except UnicodeDecodeError:
reason = self.reason.decode("iso-8859-1")
else:
reason = self.reason

if 400 <= self.status_code < 500:
http_error_msg = (
f"{self.status_code} Client Error: {reason} for url: {self.url}"
)

elif 500 <= self.status_code < 600:
http_error_msg = (
f"{self.status_code} Server Error: {reason} for url: {self.url}"
)

if http_error_msg:
> raise HTTPError(http_error_msg, response=self)
E requests.exceptions.HTTPError: 400 Client Error: Bad Request for url: https://addons.allizom.org/api/v5/addons/addon/

venv/lib/python3.11/site-packages/requests/models.py:1024: HTTPError
------------------------------Captured stdout call------------------------------
Session Token: ldvd5ag27bkfpukx6rn2lcj0yuvakt3v Uploading to: https://addons.allizom.org/api/v5/addons/upload/
Failed tests/api_w/test_addon_uploads.py::test_upload_addon_with_broken_archives[A "tar" compression renamed as "zip"] 51.95
self = <urllib3.connection.HTTPSConnection object at 0x1039ec690>

def _new_conn(self) -> socket.socket:
"""Establish a socket connection and set nodelay settings on it.

:return: New socket connection.
"""
try:
> sock = connection.create_connection(
(self._dns_host, self.port),
self.timeout,
source_address=self.source_address,
socket_options=self.socket_options,
)

venv/lib/python3.11/site-packages/urllib3/connection.py:196:
_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _
venv/lib/python3.11/site-packages/urllib3/util/connection.py:60: in create_connection
for res in socket.getaddrinfo(host, port, family, socket.SOCK_STREAM):
_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _

host = 'addons.allizom.org', port = 443, family = <AddressFamily.AF_UNSPEC: 0>, type = <SocketKind.SOCK_STREAM: 1>, proto = 0, flags = 0

def getaddrinfo(host, port, family=0, type=0, proto=0, flags=0):
"""Resolve host and port into list of address info entries.

Translate the host/port argument into a sequence of 5-tuples that contain
all the necessary arguments for creating a socket connected to that service.
host is a domain name, a string representation of an IPv4/v6 address or
None. port is a string service name such as 'http', a numeric port number or
None. By passing None as the value of host and port, you can pass NULL to
the underlying C API.

The family, type and proto arguments can be optionally specified in order to
narrow the list of addresses returned. Passing zero as a value for each of
these arguments selects the full range of results.
"""
# We override this function since we want to translate the numeric family
# and socket type values to enum constants.
addrlist = []
> for res in _socket.getaddrinfo(host, port, family, type, proto, flags):
E socket.gaierror: [Errno 8] nodename nor servname provided, or not known

/Library/Frameworks/Python.framework/Versions/3.11/lib/python3.11/socket.py:962: gaierror

The above exception was the direct cause of the following exception:

self = <urllib3.connectionpool.HTTPSConnectionPool object at 0x10393b4d0>, method = 'GET', url = '/api/v5/addons/upload/cb0b9005796d46e6ab29a636175f5a5f', body = None
headers = {'User-Agent': 'python-requests/2.32.0', 'Accept-Encoding': 'gzip, deflate', 'Accept': '*/*', 'Connection': 'keep-alive', 'Authorization': 'Session ldvd5ag27bkfpukx6rn2lcj0yuvakt3v'}
retries = Retry(total=0, connect=None, read=False, redirect=None, status=None), redirect = False, assert_same_host = False, timeout = Timeout(connect=None, read=None, total=None), pool_timeout = None
release_conn = False, chunked = False, body_pos = None, preload_content = False, decode_content = False, response_kw = {}
parsed_url = Url(scheme=None, auth=None, host=None, port=None, path='/api/v5/addons/upload/cb0b9005796d46e6ab29a636175f5a5f', query=None, fragment=None), destination_scheme = None, conn = None
release_this_conn = True, http_tunnel_required = False, err = None, clean_exit = False

def urlopen( # type: ignore[override]
self,
method: str,
url: str,
body: _TYPE_BODY | None = None,
headers: typing.Mapping[str, str] | None = None,
retries: Retry | bool | int | None = None,
redirect: bool = True,
assert_same_host: bool = True,
timeout: _TYPE_TIMEOUT = _DEFAULT_TIMEOUT,
pool_timeout: int | None = None,
release_conn: bool | None = None,
chunked: bool = False,
body_pos: _TYPE_BODY_POSITION | None = None,
preload_content: bool = True,
decode_content: bool = True,
**response_kw: typing.Any,
) -> BaseHTTPResponse:
"""
Get a connection from the pool and perform an HTTP request. This is the
lowest level call for making a request, so you'll need to specify all
the raw details.

.. note::

More commonly, it's appropriate to use a convenience method
such as :meth:`request`.

.. note::

`release_conn` will only behave as expected if
`preload_content=False` because we want to make
`preload_content=False` the default behaviour someday soon without
breaking backwards compatibility.

:param method:
HTTP request method (such as GET, POST, PUT, etc.)

:param url:
The URL to perform the request on.

:param body:
Data to send in the request body, either :class:`str`, :class:`bytes`,
an iterable of :class:`str`/:class:`bytes`, or a file-like object.

:param headers:
Dictionary of custom headers to send, such as User-Agent,
If-None-Match, etc. If None, pool headers are used. If provided,
these headers completely replace any pool-specific headers.

:param retries:
Configure the number of retries to allow before raising a
:class:`~urllib3.exceptions.MaxRetryError` exception.

If ``None`` (default) will retry 3 times, see ``Retry.DEFAULT``. Pass a
:class:`~urllib3.util.retry.Retry` object for fine-grained control
over different types of retries.
Pass an integer number to retry connection errors that many times,
but no other types of errors. Pass zero to never retry.

If ``False``, then retries are disabled and any exception is raised
immediately. Also, instead of raising a MaxRetryError on redirects,
the redirect response will be returned.

:type retries: :class:`~urllib3.util.retry.Retry`, False, or an int.

:param redirect:
If True, automatically handle redirects (status codes 301, 302,
303, 307, 308). Each redirect counts as a retry. Disabling retries
will disable redirect, too.

:param assert_same_host:
If ``True``, will make sure that the host of the pool requests is
consistent else will raise HostChangedError. When ``False``, you can
use the pool on an HTTP proxy and request foreign hosts.

:param timeout:
If specified, overrides the default timeout for this one
request. It may be a float (in seconds) or an instance of
:class:`urllib3.util.Timeout`.

:param pool_timeout:
If set and the pool is set to block=True, then this method will
block for ``pool_timeout`` seconds and raise EmptyPoolError if no
connection is available within the time period.

:param bool preload_content:
If True, the response's body will be preloaded into memory.

:param bool decode_content:
If True, will attempt to decode the body based on the
'content-encoding' header.

:param release_conn:
If False, then the urlopen call will not release the connection
back into the pool once a response is received (but will release if
you read the entire contents of the response such as when
`preload_content=True`). This is useful if you're not preloading
the response's content immediately. You will need to call
``r.release_conn()`` on the response ``r`` to return the connection
back into the pool. If None, it takes the value of ``preload_content``
which defaults to ``True``.

:param bool chunked:
If True, urllib3 will send the body using chunked transfer
encoding. Otherwise, urllib3 will send the body using the standard
content-length form. Defaults to False.

:param int body_pos:
Position to seek to in file-like body in the event of a retry or
redirect. Typically this won't need to be set because urllib3 will
auto-populate the value when needed.
"""
parsed_url = parse_url(url)
destination_scheme = parsed_url.scheme

if headers is None:
headers = self.headers

if not isinstance(retries, Retry):
retries = Retry.from_int(retries, redirect=redirect, default=self.retries)

if release_conn is None:
release_conn = preload_content

# Check host
if assert_same_host and not self.is_same_host(url):
raise HostChangedError(self, url, retries)

# Ensure that the URL we're connecting to is properly encoded
if url.startswith("/"):
url = to_str(_encode_target(url))
else:
url = to_str(parsed_url.url)

conn = None

# Track whether `conn` needs to be released before
# returning/raising/recursing. Update this variable if necessary, and
# leave `release_conn` constant throughout the function. That way, if
# the function recurses, the original value of `release_conn` will be
# passed down into the recursive call, and its value will be respected.
#
# See issue #651 [1] for details.
#
# [1] <https://github.com/urllib3/urllib3/issues/651>
release_this_conn = release_conn

http_tunnel_required = connection_requires_http_tunnel(
self.proxy, self.proxy_config, destination_scheme
)

# Merge the proxy headers. Only done when not using HTTP CONNECT. We
# have to copy the headers dict so we can safely change it without those
# changes being reflected in anyone else's copy.
if not http_tunnel_required:
headers = headers.copy() # type: ignore[attr-defined]
headers.update(self.proxy_headers) # type: ignore[union-attr]

# Must keep the exception bound to a separate variable or else Python 3
# complains about UnboundLocalError.
err = None

# Keep track of whether we cleanly exited the except block. This
# ensures we do proper cleanup in finally.
clean_exit = False

# Rewind body position, if needed. Record current position
# for future rewinds in the event of a redirect/retry.
body_pos = set_file_position(body, body_pos)

try:
# Request a connection from the queue.
timeout_obj = self._get_timeout(timeout)
conn = self._get_conn(timeout=pool_timeout)

conn.timeout = timeout_obj.connect_timeout # type: ignore[assignment]

# Is this a closed/new connection that requires CONNECT tunnelling?
if self.proxy is not None and http_tunnel_required and conn.is_closed:
try:
self._prepare_proxy(conn)
except (BaseSSLError, OSError, SocketTimeout) as e:
self._raise_timeout(
err=e, url=self.proxy.url, timeout_value=conn.timeout
)
raise

# If we're going to release the connection in ``finally:``, then
# the response doesn't need to know about the connection. Otherwise
# it will also try to release it and we'll have a double-release
# mess.
response_conn = conn if not release_conn else None

# Make the request on the HTTPConnection object
> response = self._make_request(
conn,
method,
url,
timeout=timeout_obj,
body=body,
headers=headers,
chunked=chunked,
retries=retries,
response_conn=response_conn,
preload_content=preload_content,
decode_content=decode_content,
**response_kw,
)

venv/lib/python3.11/site-packages/urllib3/connectionpool.py:789:
_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _
venv/lib/python3.11/site-packages/urllib3/connectionpool.py:490: in _make_request
raise new_e
venv/lib/python3.11/site-packages/urllib3/connectionpool.py:466: in _make_request
self._validate_conn(conn)
venv/lib/python3.11/site-packages/urllib3/connectionpool.py:1095: in _validate_conn
conn.connect()
venv/lib/python3.11/site-packages/urllib3/connection.py:615: in connect
self.sock = sock = self._new_conn()
_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _

self = <urllib3.connection.HTTPSConnection object at 0x1039ec690>

def _new_conn(self) -> socket.socket:
"""Establish a socket connection and set nodelay settings on it.

:return: New socket connection.
"""
try:
sock = connection.create_connection(
(self._dns_host, self.port),
self.timeout,
source_address=self.source_address,
socket_options=self.socket_options,
)
except socket.gaierror as e:
> raise NameResolutionError(self.host, self, e) from e
E urllib3.exceptions.NameResolutionError: <urllib3.connection.HTTPSConnection object at 0x1039ec690>: Failed to resolve 'addons.allizom.org' ([Errno 8] nodename nor servname provided, or not known)

venv/lib/python3.11/site-packages/urllib3/connection.py:203: NameResolutionError

The above exception was the direct cause of the following exception:

self = <requests.adapters.HTTPAdapter object at 0x103b35550>, request = <PreparedRequest [GET]>, stream = False, timeout = Timeout(connect=None, read=None, total=None), verify = True, cert = None
proxies = OrderedDict()

def send(
self, request, stream=False, timeout=None, verify=True, cert=None, proxies=None
):
"""Sends PreparedRequest object. Returns Response object.

:param request: The :class:`PreparedRequest <PreparedRequest>` being sent.
:param stream: (optional) Whether to stream the request content.
:param timeout: (optional) How long to wait for the server to send
data before giving up, as a float, or a :ref:`(connect timeout,
read timeout) <timeouts>` tuple.
:type timeout: float or tuple or urllib3 Timeout object
:param verify: (optional) Either a boolean, in which case it controls whether
we verify the server's TLS certificate, or a string, in which case it
must be a path to a CA bundle to use
:param cert: (optional) Any user-provided SSL certificate to be trusted.
:param proxies: (optional) The proxies dictionary to apply to the request.
:rtype: requests.Response
"""

try:
conn = self._get_connection(request, verify, proxies=proxies, cert=cert)
except LocationValueError as e:
raise InvalidURL(e, request=request)

self.cert_verify(conn, request.url, verify, cert)
url = self.request_url(request, proxies)
self.add_headers(
request,
stream=stream,
timeout=timeout,
verify=verify,
cert=cert,
proxies=proxies,
)

chunked = not (request.body is None or "Content-Length" in request.headers)

if isinstance(timeout, tuple):
try:
connect, read = timeout
timeout = TimeoutSauce(connect=connect, read=read)
except ValueError:
raise ValueError(
f"Invalid timeout {timeout}. Pass a (connect, read) timeout tuple, "
f"or a single float to set both timeouts to the same value."
)
elif isinstance(timeout, TimeoutSauce):
pass
else:
timeout = TimeoutSauce(connect=timeout, read=timeout)

try:
> resp = conn.urlopen(
method=request.method,
url=url,
body=request.body,
headers=request.headers,
redirect=False,
assert_same_host=False,
preload_content=False,
decode_content=False,
retries=self.max_retries,
timeout=timeout,
chunked=chunked,
)

venv/lib/python3.11/site-packages/requests/adapters.py:564:
_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _
venv/lib/python3.11/site-packages/urllib3/connectionpool.py:843: in urlopen
retries = retries.increment(
_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _

self = Retry(total=0, connect=None, read=False, redirect=None, status=None), method = 'GET', url = '/api/v5/addons/upload/cb0b9005796d46e6ab29a636175f5a5f', response = None
error = NameResolutionError("<urllib3.connection.HTTPSConnection object at 0x1039ec690>: Failed to resolve 'addons.allizom.org' ([Errno 8] nodename nor servname provided, or not known)")
_pool = <urllib3.connectionpool.HTTPSConnectionPool object at 0x10393b4d0>, _stacktrace = <traceback object at 0x1039ec480>

def increment(
self,
method: str | None = None,
url: str | None = None,
response: BaseHTTPResponse | None = None,
error: Exception | None = None,
_pool: ConnectionPool | None = None,
_stacktrace: TracebackType | None = None,
) -> Self:
"""Return a new Retry object with incremented retry counters.

:param response: A response object, or None, if the server did not
return a response.
:type response: :class:`~urllib3.response.BaseHTTPResponse`
:param Exception error: An error encountered during the request, or
None if the response was received successfully.

:return: A new ``Retry`` object.
"""
if self.total is False and error:
# Disabled, indicate to re-raise the error.
raise reraise(type(error), error, _stacktrace)

total = self.total
if total is not None:
total -= 1

connect = self.connect
read = self.read
redirect = self.redirect
status_count = self.status
other = self.other
cause = "unknown"
status = None
redirect_location = None

if error and self._is_connection_error(error):
# Connect retry?
if connect is False:
raise reraise(type(error), error, _stacktrace)
elif connect is not None:
connect -= 1

elif error and self._is_read_error(error):
# Read retry?
if read is False or method is None or not self._is_method_retryable(method):
raise reraise(type(error), error, _stacktrace)
elif read is not None:
read -= 1

elif error:
# Other retry?
if other is not None:
other -= 1

elif response and response.get_redirect_location():
# Redirect retry?
if redirect is not None:
redirect -= 1
cause = "too many redirects"
response_redirect_location = response.get_redirect_location()
if response_redirect_location:
redirect_location = response_redirect_location
status = response.status

else:
# Incrementing because of a server error like a 500 in
# status_forcelist and the given method is in the allowed_methods
cause = ResponseError.GENERIC_ERROR
if response and response.status:
if status_count is not None:
status_count -= 1
cause = ResponseError.SPECIFIC_ERROR.format(status_code=response.status)
status = response.status

history = self.history + (
RequestHistory(method, url, error, status, redirect_location),
)

new_retry = self.new(
total=total,
connect=connect,
read=read,
redirect=redirect,
status=status_count,
other=other,
history=history,
)

if new_retry.is_exhausted():
reason = error or ResponseError(cause)
> raise MaxRetryError(_pool, url, reason) from reason # type: ignore[arg-type]
E urllib3.exceptions.MaxRetryError: HTTPSConnectionPool(host='addons.allizom.org', port=443): Max retries exceeded with url: /api/v5/addons/upload/cb0b9005796d46e6ab29a636175f5a5f (Caused by NameResolutionError("<urllib3.connection.HTTPSConnection object at 0x1039ec690>: Failed to resolve 'addons.allizom.org' ([Errno 8] nodename nor servname provided, or not known)"))

venv/lib/python3.11/site-packages/urllib3/util/retry.py:519: MaxRetryError

During handling of the above exception, another exception occurred:

base_url = 'https://addons.allizom.org', session_auth = 'ldvd5ag27bkfpukx6rn2lcj0yuvakt3v', file_type = 'tar-renamed-as-zip.zip'

@pytest.mark.parametrize(
"file_type",
[
"tar-renamed-as-zip.zip",
"broken-archive.zip",
],
ids=[
'A "tar" compression renamed as "zip"',
"Corrupt archive",
],
)
@pytest.mark.serial
@pytest.mark.create_session("api_user")
def test_upload_addon_with_broken_archives(base_url, session_auth, file_type):
"""Try to upload an addon with a corrupt or invalid archive and check that the
validation message identifies them as such; for example, a 'tar' compression
renamed to look as a 'zip' file should be detected as invalid"""
with open(f"sample-addons/{file_type}", "rb") as file:
upload = requests.post(
url=f"{base_url}{_upload}",
headers={"Authorization": f"Session {session_auth}"},
files={"upload": file},
data={"channel": "unlisted"},
)
time.sleep(5)
upload.raise_for_status()
uuid = upload.json()["uuid"]
payload = payloads.listed_addon_minimal(uuid)
create_addon = requests.post(
url=f"{base_url}{_addon_create}",
headers={
"Authorization": f"Session {session_auth}",
"Content-Type": "application/json",
},
data=json.dumps(payload),
)
assert (
create_addon.status_code == 400
), f"Actual response: {create_addon.status_code}, {create_addon.text}"
# get the validation messages returned by the API
> validation = requests.get(
url=f"{base_url}{_upload}{uuid}",
headers={"Authorization": f"Session {session_auth}"},
)

tests/api_w/test_addon_uploads.py:204:
_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _
venv/lib/python3.11/site-packages/requests/api.py:73: in get
return request("get", url, params=params, **kwargs)
venv/lib/python3.11/site-packages/requests/api.py:59: in request
return session.request(method=method, url=url, **kwargs)
venv/lib/python3.11/site-packages/requests/sessions.py:589: in request
resp = self.send(prep, **send_kwargs)
venv/lib/python3.11/site-packages/requests/sessions.py:703: in send
r = adapter.send(request, **kwargs)
_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _

self = <requests.adapters.HTTPAdapter object at 0x103b35550>, request = <PreparedRequest [GET]>, stream = False, timeout = Timeout(connect=None, read=None, total=None), verify = True, cert = None
proxies = OrderedDict()

def send(
self, request, stream=False, timeout=None, verify=True, cert=None, proxies=None
):
"""Sends PreparedRequest object. Returns Response object.

:param request: The :class:`PreparedRequest <PreparedRequest>` being sent.
:param stream: (optional) Whether to stream the request content.
:param timeout: (optional) How long to wait for the server to send
data before giving up, as a float, or a :ref:`(connect timeout,
read timeout) <timeouts>` tuple.
:type timeout: float or tuple or urllib3 Timeout object
:param verify: (optional) Either a boolean, in which case it controls whether
we verify the server's TLS certificate, or a string, in which case it
must be a path to a CA bundle to use
:param cert: (optional) Any user-provided SSL certificate to be trusted.
:param proxies: (optional) The proxies dictionary to apply to the request.
:rtype: requests.Response
"""

try:
conn = self._get_connection(request, verify, proxies=proxies, cert=cert)
except LocationValueError as e:
raise InvalidURL(e, request=request)

self.cert_verify(conn, request.url, verify, cert)
url = self.request_url(request, proxies)
self.add_headers(
request,
stream=stream,
timeout=timeout,
verify=verify,
cert=cert,
proxies=proxies,
)

chunked = not (request.body is None or "Content-Length" in request.headers)

if isinstance(timeout, tuple):
try:
connect, read = timeout
timeout = TimeoutSauce(connect=connect, read=read)
except ValueError:
raise ValueError(
f"Invalid timeout {timeout}. Pass a (connect, read) timeout tuple, "
f"or a single float to set both timeouts to the same value."
)
elif isinstance(timeout, TimeoutSauce):
pass
else:
timeout = TimeoutSauce(connect=timeout, read=timeout)

try:
resp = conn.urlopen(
method=request.method,
url=url,
body=request.body,
headers=request.headers,
redirect=False,
assert_same_host=False,
preload_content=False,
decode_content=False,
retries=self.max_retries,
timeout=timeout,
chunked=chunked,
)

except (ProtocolError, OSError) as err:
raise ConnectionError(err, request=request)

except MaxRetryError as e:
if isinstance(e.reason, ConnectTimeoutError):
# TODO: Remove this in 3.0.0: see #2811
if not isinstance(e.reason, NewConnectionError):
raise ConnectTimeout(e, request=request)

if isinstance(e.reason, ResponseError):
raise RetryError(e, request=request)

if isinstance(e.reason, _ProxyError):
raise ProxyError(e, request=request)

if isinstance(e.reason, _SSLError):
# This branch is for urllib3 v1.22 and later.
raise SSLError(e, request=request)

> raise ConnectionError(e, request=request)
E requests.exceptions.ConnectionError: HTTPSConnectionPool(host='addons.allizom.org', port=443): Max retries exceeded with url: /api/v5/addons/upload/cb0b9005796d46e6ab29a636175f5a5f (Caused by NameResolutionError("<urllib3.connection.HTTPSConnection object at 0x1039ec690>: Failed to resolve 'addons.allizom.org' ([Errno 8] nodename nor servname provided, or not known)"))

venv/lib/python3.11/site-packages/requests/adapters.py:597: ConnectionError
Failed tests/api_w/test_addon_uploads.py::test_upload_addon_with_broken_archives[Corrupt archive] 17.65
self = <urllib3.connection.HTTPSConnection object at 0x10397ad10>

def _new_conn(self) -> socket.socket:
"""Establish a socket connection and set nodelay settings on it.

:return: New socket connection.
"""
try:
> sock = connection.create_connection(
(self._dns_host, self.port),
self.timeout,
source_address=self.source_address,
socket_options=self.socket_options,
)

venv/lib/python3.11/site-packages/urllib3/connection.py:196:
_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _
venv/lib/python3.11/site-packages/urllib3/util/connection.py:60: in create_connection
for res in socket.getaddrinfo(host, port, family, socket.SOCK_STREAM):
_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _

host = 'addons.allizom.org', port = 443, family = <AddressFamily.AF_UNSPEC: 0>, type = <SocketKind.SOCK_STREAM: 1>, proto = 0, flags = 0

def getaddrinfo(host, port, family=0, type=0, proto=0, flags=0):
"""Resolve host and port into list of address info entries.

Translate the host/port argument into a sequence of 5-tuples that contain
all the necessary arguments for creating a socket connected to that service.
host is a domain name, a string representation of an IPv4/v6 address or
None. port is a string service name such as 'http', a numeric port number or
None. By passing None as the value of host and port, you can pass NULL to
the underlying C API.

The family, type and proto arguments can be optionally specified in order to
narrow the list of addresses returned. Passing zero as a value for each of
these arguments selects the full range of results.
"""
# We override this function since we want to translate the numeric family
# and socket type values to enum constants.
addrlist = []
> for res in _socket.getaddrinfo(host, port, family, type, proto, flags):
E socket.gaierror: [Errno 8] nodename nor servname provided, or not known

/Library/Frameworks/Python.framework/Versions/3.11/lib/python3.11/socket.py:962: gaierror

The above exception was the direct cause of the following exception:

self = <urllib3.connectionpool.HTTPSConnectionPool object at 0x10397aa10>, method = 'POST', url = '/api/v5/addons/upload/'
body = b'--8494166f569e967c4aa33ffda0c9e63c\r\nContent-Disposition: form-data; name="channel"\r\n\r\nunlisted\r\n--8494166f56...5\x06\x00\x00\x00\x00\x01\x00\x01\x00_\x00\x00\x00\x81\x00\x00\x00\x00\x00\r\n--8494166f569e967c4aa33ffda0c9e63c--\r\n'
headers = {'User-Agent': 'python-requests/2.32.0', 'Accept-Encoding': 'gzip, deflate', 'Accept': '*/*', 'Connection': 'keep-aliv...j0yuvakt3v', 'Content-Length': '445', 'Content-Type': 'multipart/form-data; boundary=8494166f569e967c4aa33ffda0c9e63c'}
retries = Retry(total=0, connect=None, read=False, redirect=None, status=None), redirect = False, assert_same_host = False, timeout = Timeout(connect=None, read=None, total=None), pool_timeout = None
release_conn = False, chunked = False, body_pos = None, preload_content = False, decode_content = False, response_kw = {}
parsed_url = Url(scheme=None, auth=None, host=None, port=None, path='/api/v5/addons/upload/', query=None, fragment=None), destination_scheme = None, conn = None, release_this_conn = True
http_tunnel_required = False, err = None, clean_exit = False

def urlopen( # type: ignore[override]
self,
method: str,
url: str,
body: _TYPE_BODY | None = None,
headers: typing.Mapping[str, str] | None = None,
retries: Retry | bool | int | None = None,
redirect: bool = True,
assert_same_host: bool = True,
timeout: _TYPE_TIMEOUT = _DEFAULT_TIMEOUT,
pool_timeout: int | None = None,
release_conn: bool | None = None,
chunked: bool = False,
body_pos: _TYPE_BODY_POSITION | None = None,
preload_content: bool = True,
decode_content: bool = True,
**response_kw: typing.Any,
) -> BaseHTTPResponse:
"""
Get a connection from the pool and perform an HTTP request. This is the
lowest level call for making a request, so you'll need to specify all
the raw details.

.. note::

More commonly, it's appropriate to use a convenience method
such as :meth:`request`.

.. note::

`release_conn` will only behave as expected if
`preload_content=False` because we want to make
`preload_content=False` the default behaviour someday soon without
breaking backwards compatibility.

:param method:
HTTP request method (such as GET, POST, PUT, etc.)

:param url:
The URL to perform the request on.

:param body:
Data to send in the request body, either :class:`str`, :class:`bytes`,
an iterable of :class:`str`/:class:`bytes`, or a file-like object.

:param headers:
Dictionary of custom headers to send, such as User-Agent,
If-None-Match, etc. If None, pool headers are used. If provided,
these headers completely replace any pool-specific headers.

:param retries:
Configure the number of retries to allow before raising a
:class:`~urllib3.exceptions.MaxRetryError` exception.

If ``None`` (default) will retry 3 times, see ``Retry.DEFAULT``. Pass a
:class:`~urllib3.util.retry.Retry` object for fine-grained control
over different types of retries.
Pass an integer number to retry connection errors that many times,
but no other types of errors. Pass zero to never retry.

If ``False``, then retries are disabled and any exception is raised
immediately. Also, instead of raising a MaxRetryError on redirects,
the redirect response will be returned.

:type retries: :class:`~urllib3.util.retry.Retry`, False, or an int.

:param redirect:
If True, automatically handle redirects (status codes 301, 302,
303, 307, 308). Each redirect counts as a retry. Disabling retries
will disable redirect, too.

:param assert_same_host:
If ``True``, will make sure that the host of the pool requests is
consistent else will raise HostChangedError. When ``False``, you can
use the pool on an HTTP proxy and request foreign hosts.

:param timeout:
If specified, overrides the default timeout for this one
request. It may be a float (in seconds) or an instance of
:class:`urllib3.util.Timeout`.

:param pool_timeout:
If set and the pool is set to block=True, then this method will
block for ``pool_timeout`` seconds and raise EmptyPoolError if no
connection is available within the time period.

:param bool preload_content:
If True, the response's body will be preloaded into memory.

:param bool decode_content:
If True, will attempt to decode the body based on the
'content-encoding' header.

:param release_conn:
If False, then the urlopen call will not release the connection
back into the pool once a response is received (but will release if
you read the entire contents of the response such as when
`preload_content=True`). This is useful if you're not preloading
the response's content immediately. You will need to call
``r.release_conn()`` on the response ``r`` to return the connection
back into the pool. If None, it takes the value of ``preload_content``
which defaults to ``True``.

:param bool chunked:
If True, urllib3 will send the body using chunked transfer
encoding. Otherwise, urllib3 will send the body using the standard
content-length form. Defaults to False.

:param int body_pos:
Position to seek to in file-like body in the event of a retry or
redirect. Typically this won't need to be set because urllib3 will
auto-populate the value when needed.
"""
parsed_url = parse_url(url)
destination_scheme = parsed_url.scheme

if headers is None:
headers = self.headers

if not isinstance(retries, Retry):
retries = Retry.from_int(retries, redirect=redirect, default=self.retries)

if release_conn is None:
release_conn = preload_content

# Check host
if assert_same_host and not self.is_same_host(url):
raise HostChangedError(self, url, retries)

# Ensure that the URL we're connecting to is properly encoded
if url.startswith("/"):
url = to_str(_encode_target(url))
else:
url = to_str(parsed_url.url)

conn = None

# Track whether `conn` needs to be released before
# returning/raising/recursing. Update this variable if necessary, and
# leave `release_conn` constant throughout the function. That way, if
# the function recurses, the original value of `release_conn` will be
# passed down into the recursive call, and its value will be respected.
#
# See issue #651 [1] for details.
#
# [1] <https://github.com/urllib3/urllib3/issues/651>
release_this_conn = release_conn

http_tunnel_required = connection_requires_http_tunnel(
self.proxy, self.proxy_config, destination_scheme
)

# Merge the proxy headers. Only done when not using HTTP CONNECT. We
# have to copy the headers dict so we can safely change it without those
# changes being reflected in anyone else's copy.
if not http_tunnel_required:
headers = headers.copy() # type: ignore[attr-defined]
headers.update(self.proxy_headers) # type: ignore[union-attr]

# Must keep the exception bound to a separate variable or else Python 3
# complains about UnboundLocalError.
err = None

# Keep track of whether we cleanly exited the except block. This
# ensures we do proper cleanup in finally.
clean_exit = False

# Rewind body position, if needed. Record current position
# for future rewinds in the event of a redirect/retry.
body_pos = set_file_position(body, body_pos)

try:
# Request a connection from the queue.
timeout_obj = self._get_timeout(timeout)
conn = self._get_conn(timeout=pool_timeout)

conn.timeout = timeout_obj.connect_timeout # type: ignore[assignment]

# Is this a closed/new connection that requires CONNECT tunnelling?
if self.proxy is not None and http_tunnel_required and conn.is_closed:
try:
self._prepare_proxy(conn)
except (BaseSSLError, OSError, SocketTimeout) as e:
self._raise_timeout(
err=e, url=self.proxy.url, timeout_value=conn.timeout
)
raise

# If we're going to release the connection in ``finally:``, then
# the response doesn't need to know about the connection. Otherwise
# it will also try to release it and we'll have a double-release
# mess.
response_conn = conn if not release_conn else None

# Make the request on the HTTPConnection object
> response = self._make_request(
conn,
method,
url,
timeout=timeout_obj,
body=body,
headers=headers,
chunked=chunked,
retries=retries,
response_conn=response_conn,
preload_content=preload_content,
decode_content=decode_content,
**response_kw,
)

venv/lib/python3.11/site-packages/urllib3/connectionpool.py:789:
_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _
venv/lib/python3.11/site-packages/urllib3/connectionpool.py:490: in _make_request
raise new_e
venv/lib/python3.11/site-packages/urllib3/connectionpool.py:466: in _make_request
self._validate_conn(conn)
venv/lib/python3.11/site-packages/urllib3/connectionpool.py:1095: in _validate_conn
conn.connect()
venv/lib/python3.11/site-packages/urllib3/connection.py:615: in connect
self.sock = sock = self._new_conn()
_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _

self = <urllib3.connection.HTTPSConnection object at 0x10397ad10>

def _new_conn(self) -> socket.socket:
"""Establish a socket connection and set nodelay settings on it.

:return: New socket connection.
"""
try:
sock = connection.create_connection(
(self._dns_host, self.port),
self.timeout,
source_address=self.source_address,
socket_options=self.socket_options,
)
except socket.gaierror as e:
> raise NameResolutionError(self.host, self, e) from e
E urllib3.exceptions.NameResolutionError: <urllib3.connection.HTTPSConnection object at 0x10397ad10>: Failed to resolve 'addons.allizom.org' ([Errno 8] nodename nor servname provided, or not known)

venv/lib/python3.11/site-packages/urllib3/connection.py:203: NameResolutionError

The above exception was the direct cause of the following exception:

self = <requests.adapters.HTTPAdapter object at 0x103955510>, request = <PreparedRequest [POST]>, stream = False, timeout = Timeout(connect=None, read=None, total=None), verify = True, cert = None
proxies = OrderedDict()

def send(
self, request, stream=False, timeout=None, verify=True, cert=None, proxies=None
):
"""Sends PreparedRequest object. Returns Response object.

:param request: The :class:`PreparedRequest <PreparedRequest>` being sent.
:param stream: (optional) Whether to stream the request content.
:param timeout: (optional) How long to wait for the server to send
data before giving up, as a float, or a :ref:`(connect timeout,
read timeout) <timeouts>` tuple.
:type timeout: float or tuple or urllib3 Timeout object
:param verify: (optional) Either a boolean, in which case it controls whether
we verify the server's TLS certificate, or a string, in which case it
must be a path to a CA bundle to use
:param cert: (optional) Any user-provided SSL certificate to be trusted.
:param proxies: (optional) The proxies dictionary to apply to the request.
:rtype: requests.Response
"""

try:
conn = self._get_connection(request, verify, proxies=proxies, cert=cert)
except LocationValueError as e:
raise InvalidURL(e, request=request)

self.cert_verify(conn, request.url, verify, cert)
url = self.request_url(request, proxies)
self.add_headers(
request,
stream=stream,
timeout=timeout,
verify=verify,
cert=cert,
proxies=proxies,
)

chunked = not (request.body is None or "Content-Length" in request.headers)

if isinstance(timeout, tuple):
try:
connect, read = timeout
timeout = TimeoutSauce(connect=connect, read=read)
except ValueError:
raise ValueError(
f"Invalid timeout {timeout}. Pass a (connect, read) timeout tuple, "
f"or a single float to set both timeouts to the same value."
)
elif isinstance(timeout, TimeoutSauce):
pass
else:
timeout = TimeoutSauce(connect=timeout, read=timeout)

try:
> resp = conn.urlopen(
method=request.method,
url=url,
body=request.body,
headers=request.headers,
redirect=False,
assert_same_host=False,
preload_content=False,
decode_content=False,
retries=self.max_retries,
timeout=timeout,
chunked=chunked,
)

venv/lib/python3.11/site-packages/requests/adapters.py:564:
_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _
venv/lib/python3.11/site-packages/urllib3/connectionpool.py:843: in urlopen
retries = retries.increment(
_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _

self = Retry(total=0, connect=None, read=False, redirect=None, status=None), method = 'POST', url = '/api/v5/addons/upload/', response = None
error = NameResolutionError("<urllib3.connection.HTTPSConnection object at 0x10397ad10>: Failed to resolve 'addons.allizom.org' ([Errno 8] nodename nor servname provided, or not known)")
_pool = <urllib3.connectionpool.HTTPSConnectionPool object at 0x10397aa10>, _stacktrace = <traceback object at 0x10397ab40>

def increment(
self,
method: str | None = None,
url: str | None = None,
response: BaseHTTPResponse | None = None,
error: Exception | None = None,
_pool: ConnectionPool | None = None,
_stacktrace: TracebackType | None = None,
) -> Self:
"""Return a new Retry object with incremented retry counters.

:param response: A response object, or None, if the server did not
return a response.
:type response: :class:`~urllib3.response.BaseHTTPResponse`
:param Exception error: An error encountered during the request, or
None if the response was received successfully.

:return: A new ``Retry`` object.
"""
if self.total is False and error:
# Disabled, indicate to re-raise the error.
raise reraise(type(error), error, _stacktrace)

total = self.total
if total is not None:
total -= 1

connect = self.connect
read = self.read
redirect = self.redirect
status_count = self.status
other = self.other
cause = "unknown"
status = None
redirect_location = None

if error and self._is_connection_error(error):
# Connect retry?
if connect is False:
raise reraise(type(error), error, _stacktrace)
elif connect is not None:
connect -= 1

elif error and self._is_read_error(error):
# Read retry?
if read is False or method is None or not self._is_method_retryable(method):
raise reraise(type(error), error, _stacktrace)
elif read is not None:
read -= 1

elif error:
# Other retry?
if other is not None:
other -= 1

elif response and response.get_redirect_location():
# Redirect retry?
if redirect is not None:
redirect -= 1
cause = "too many redirects"
response_redirect_location = response.get_redirect_location()
if response_redirect_location:
redirect_location = response_redirect_location
status = response.status

else:
# Incrementing because of a server error like a 500 in
# status_forcelist and the given method is in the allowed_methods
cause = ResponseError.GENERIC_ERROR
if response and response.status:
if status_count is not None:
status_count -= 1
cause = ResponseError.SPECIFIC_ERROR.format(status_code=response.status)
status = response.status

history = self.history + (
RequestHistory(method, url, error, status, redirect_location),
)

new_retry = self.new(
total=total,
connect=connect,
read=read,
redirect=redirect,
status=status_count,
other=other,
history=history,
)

if new_retry.is_exhausted():
reason = error or ResponseError(cause)
> raise MaxRetryError(_pool, url, reason) from reason # type: ignore[arg-type]
E urllib3.exceptions.MaxRetryError: HTTPSConnectionPool(host='addons.allizom.org', port=443): Max retries exceeded with url: /api/v5/addons/upload/ (Caused by NameResolutionError("<urllib3.connection.HTTPSConnection object at 0x10397ad10>: Failed to resolve 'addons.allizom.org' ([Errno 8] nodename nor servname provided, or not known)"))

venv/lib/python3.11/site-packages/urllib3/util/retry.py:519: MaxRetryError

During handling of the above exception, another exception occurred:

base_url = 'https://addons.allizom.org', session_auth = 'ldvd5ag27bkfpukx6rn2lcj0yuvakt3v', file_type = 'broken-archive.zip'

@pytest.mark.parametrize(
"file_type",
[
"tar-renamed-as-zip.zip",
"broken-archive.zip",
],
ids=[
'A "tar" compression renamed as "zip"',
"Corrupt archive",
],
)
@pytest.mark.serial
@pytest.mark.create_session("api_user")
def test_upload_addon_with_broken_archives(base_url, session_auth, file_type):
"""Try to upload an addon with a corrupt or invalid archive and check that the
validation message identifies them as such; for example, a 'tar' compression
renamed to look as a 'zip' file should be detected as invalid"""
with open(f"sample-addons/{file_type}", "rb") as file:
> upload = requests.post(
url=f"{base_url}{_upload}",
headers={"Authorization": f"Session {session_auth}"},
files={"upload": file},
data={"channel": "unlisted"},
)

tests/api_w/test_addon_uploads.py:182:
_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _
venv/lib/python3.11/site-packages/requests/api.py:115: in post
return request("post", url, data=data, json=json, **kwargs)
venv/lib/python3.11/site-packages/requests/api.py:59: in request
return session.request(method=method, url=url, **kwargs)
venv/lib/python3.11/site-packages/requests/sessions.py:589: in request
resp = self.send(prep, **send_kwargs)
venv/lib/python3.11/site-packages/requests/sessions.py:703: in send
r = adapter.send(request, **kwargs)
_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _

self = <requests.adapters.HTTPAdapter object at 0x103955510>, request = <PreparedRequest [POST]>, stream = False, timeout = Timeout(connect=None, read=None, total=None), verify = True, cert = None
proxies = OrderedDict()

def send(
self, request, stream=False, timeout=None, verify=True, cert=None, proxies=None
):
"""Sends PreparedRequest object. Returns Response object.

:param request: The :class:`PreparedRequest <PreparedRequest>` being sent.
:param stream: (optional) Whether to stream the request content.
:param timeout: (optional) How long to wait for the server to send
data before giving up, as a float, or a :ref:`(connect timeout,
read timeout) <timeouts>` tuple.
:type timeout: float or tuple or urllib3 Timeout object
:param verify: (optional) Either a boolean, in which case it controls whether
we verify the server's TLS certificate, or a string, in which case it
must be a path to a CA bundle to use
:param cert: (optional) Any user-provided SSL certificate to be trusted.
:param proxies: (optional) The proxies dictionary to apply to the request.
:rtype: requests.Response
"""

try:
conn = self._get_connection(request, verify, proxies=proxies, cert=cert)
except LocationValueError as e:
raise InvalidURL(e, request=request)

self.cert_verify(conn, request.url, verify, cert)
url = self.request_url(request, proxies)
self.add_headers(
request,
stream=stream,
timeout=timeout,
verify=verify,
cert=cert,
proxies=proxies,
)

chunked = not (request.body is None or "Content-Length" in request.headers)

if isinstance(timeout, tuple):
try:
connect, read = timeout
timeout = TimeoutSauce(connect=connect, read=read)
except ValueError:
raise ValueError(
f"Invalid timeout {timeout}. Pass a (connect, read) timeout tuple, "
f"or a single float to set both timeouts to the same value."
)
elif isinstance(timeout, TimeoutSauce):
pass
else:
timeout = TimeoutSauce(connect=timeout, read=timeout)

try:
resp = conn.urlopen(
method=request.method,
url=url,
body=request.body,
headers=request.headers,
redirect=False,
assert_same_host=False,
preload_content=False,
decode_content=False,
retries=self.max_retries,
timeout=timeout,
chunked=chunked,
)

except (ProtocolError, OSError) as err:
raise ConnectionError(err, request=request)

except MaxRetryError as e:
if isinstance(e.reason, ConnectTimeoutError):
# TODO: Remove this in 3.0.0: see #2811
if not isinstance(e.reason, NewConnectionError):
raise ConnectTimeout(e, request=request)

if isinstance(e.reason, ResponseError):
raise RetryError(e, request=request)

if isinstance(e.reason, _ProxyError):
raise ProxyError(e, request=request)

if isinstance(e.reason, _SSLError):
# This branch is for urllib3 v1.22 and later.
raise SSLError(e, request=request)

> raise ConnectionError(e, request=request)
E requests.exceptions.ConnectionError: HTTPSConnectionPool(host='addons.allizom.org', port=443): Max retries exceeded with url: /api/v5/addons/upload/ (Caused by NameResolutionError("<urllib3.connection.HTTPSConnection object at 0x10397ad10>: Failed to resolve 'addons.allizom.org' ([Errno 8] nodename nor servname provided, or not known)"))

venv/lib/python3.11/site-packages/requests/adapters.py:597: ConnectionError
Failed tests/api_w/test_addon_uploads.py::test_upload_unlisted_extension 0.06
self = <urllib3.connection.HTTPSConnection object at 0x104015090>

def _new_conn(self) -> socket.socket:
"""Establish a socket connection and set nodelay settings on it.

:return: New socket connection.
"""
try:
> sock = connection.create_connection(
(self._dns_host, self.port),
self.timeout,
source_address=self.source_address,
socket_options=self.socket_options,
)

venv/lib/python3.11/site-packages/urllib3/connection.py:196:
_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _
venv/lib/python3.11/site-packages/urllib3/util/connection.py:60: in create_connection
for res in socket.getaddrinfo(host, port, family, socket.SOCK_STREAM):
_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _

host = 'addons.allizom.org', port = 443, family = <AddressFamily.AF_UNSPEC: 0>, type = <SocketKind.SOCK_STREAM: 1>, proto = 0, flags = 0

def getaddrinfo(host, port, family=0, type=0, proto=0, flags=0):
"""Resolve host and port into list of address info entries.

Translate the host/port argument into a sequence of 5-tuples that contain
all the necessary arguments for creating a socket connected to that service.
host is a domain name, a string representation of an IPv4/v6 address or
None. port is a string service name such as 'http', a numeric port number or
None. By passing None as the value of host and port, you can pass NULL to
the underlying C API.

The family, type and proto arguments can be optionally specified in order to
narrow the list of addresses returned. Passing zero as a value for each of
these arguments selects the full range of results.
"""
# We override this function since we want to translate the numeric family
# and socket type values to enum constants.
addrlist = []
> for res in _socket.getaddrinfo(host, port, family, type, proto, flags):
E socket.gaierror: [Errno 8] nodename nor servname provided, or not known

/Library/Frameworks/Python.framework/Versions/3.11/lib/python3.11/socket.py:962: gaierror

The above exception was the direct cause of the following exception:

self = <urllib3.connectionpool.HTTPSConnectionPool object at 0x104015250>, method = 'POST', url = '/api/v5/addons/upload/'
body = b'--6231497c8871fe5d1dbdfb82604ed8c3\r\nContent-Disposition: form-data; name="channel"\r\n\r\nunlisted\r\n--6231497c88...5\x06\x00\x00\x00\x00\x01\x00\x01\x00_\x00\x00\x00\x99\x00\x00\x00\x00\x00\r\n--6231497c8871fe5d1dbdfb82604ed8c3--\r\n'
headers = {'User-Agent': 'python-requests/2.32.0', 'Accept-Encoding': 'gzip, deflate', 'Accept': '*/*', 'Connection': 'keep-aliv...j0yuvakt3v', 'Content-Length': '522', 'Content-Type': 'multipart/form-data; boundary=6231497c8871fe5d1dbdfb82604ed8c3'}
retries = Retry(total=0, connect=None, read=False, redirect=None, status=None), redirect = False, assert_same_host = False, timeout = Timeout(connect=None, read=None, total=None), pool_timeout = None
release_conn = False, chunked = False, body_pos = None, preload_content = False, decode_content = False, response_kw = {}
parsed_url = Url(scheme=None, auth=None, host=None, port=None, path='/api/v5/addons/upload/', query=None, fragment=None), destination_scheme = None, conn = None, release_this_conn = True
http_tunnel_required = False, err = None, clean_exit = False

def urlopen( # type: ignore[override]
self,
method: str,
url: str,
body: _TYPE_BODY | None = None,
headers: typing.Mapping[str, str] | None = None,
retries: Retry | bool | int | None = None,
redirect: bool = True,
assert_same_host: bool = True,
timeout: _TYPE_TIMEOUT = _DEFAULT_TIMEOUT,
pool_timeout: int | None = None,
release_conn: bool | None = None,
chunked: bool = False,
body_pos: _TYPE_BODY_POSITION | None = None,
preload_content: bool = True,
decode_content: bool = True,
**response_kw: typing.Any,
) -> BaseHTTPResponse:
"""
Get a connection from the pool and perform an HTTP request. This is the
lowest level call for making a request, so you'll need to specify all
the raw details.

.. note::

More commonly, it's appropriate to use a convenience method
such as :meth:`request`.

.. note::

`release_conn` will only behave as expected if
`preload_content=False` because we want to make
`preload_content=False` the default behaviour someday soon without
breaking backwards compatibility.

:param method:
HTTP request method (such as GET, POST, PUT, etc.)

:param url:
The URL to perform the request on.

:param body:
Data to send in the request body, either :class:`str`, :class:`bytes`,
an iterable of :class:`str`/:class:`bytes`, or a file-like object.

:param headers:
Dictionary of custom headers to send, such as User-Agent,
If-None-Match, etc. If None, pool headers are used. If provided,
these headers completely replace any pool-specific headers.

:param retries:
Configure the number of retries to allow before raising a
:class:`~urllib3.exceptions.MaxRetryError` exception.

If ``None`` (default) will retry 3 times, see ``Retry.DEFAULT``. Pass a
:class:`~urllib3.util.retry.Retry` object for fine-grained control
over different types of retries.
Pass an integer number to retry connection errors that many times,
but no other types of errors. Pass zero to never retry.

If ``False``, then retries are disabled and any exception is raised
immediately. Also, instead of raising a MaxRetryError on redirects,
the redirect response will be returned.

:type retries: :class:`~urllib3.util.retry.Retry`, False, or an int.

:param redirect:
If True, automatically handle redirects (status codes 301, 302,
303, 307, 308). Each redirect counts as a retry. Disabling retries
will disable redirect, too.

:param assert_same_host:
If ``True``, will make sure that the host of the pool requests is
consistent else will raise HostChangedError. When ``False``, you can
use the pool on an HTTP proxy and request foreign hosts.

:param timeout:
If specified, overrides the default timeout for this one
request. It may be a float (in seconds) or an instance of
:class:`urllib3.util.Timeout`.

:param pool_timeout:
If set and the pool is set to block=True, then this method will
block for ``pool_timeout`` seconds and raise EmptyPoolError if no
connection is available within the time period.

:param bool preload_content:
If True, the response's body will be preloaded into memory.

:param bool decode_content:
If True, will attempt to decode the body based on the
'content-encoding' header.

:param release_conn:
If False, then the urlopen call will not release the connection
back into the pool once a response is received (but will release if
you read the entire contents of the response such as when
`preload_content=True`). This is useful if you're not preloading
the response's content immediately. You will need to call
``r.release_conn()`` on the response ``r`` to return the connection
back into the pool. If None, it takes the value of ``preload_content``
which defaults to ``True``.

:param bool chunked:
If True, urllib3 will send the body using chunked transfer
encoding. Otherwise, urllib3 will send the body using the standard
content-length form. Defaults to False.

:param int body_pos:
Position to seek to in file-like body in the event of a retry or
redirect. Typically this won't need to be set because urllib3 will
auto-populate the value when needed.
"""
parsed_url = parse_url(url)
destination_scheme = parsed_url.scheme

if headers is None:
headers = self.headers

if not isinstance(retries, Retry):
retries = Retry.from_int(retries, redirect=redirect, default=self.retries)

if release_conn is None:
release_conn = preload_content

# Check host
if assert_same_host and not self.is_same_host(url):
raise HostChangedError(self, url, retries)

# Ensure that the URL we're connecting to is properly encoded
if url.startswith("/"):
url = to_str(_encode_target(url))
else:
url = to_str(parsed_url.url)

conn = None

# Track whether `conn` needs to be released before
# returning/raising/recursing. Update this variable if necessary, and
# leave `release_conn` constant throughout the function. That way, if
# the function recurses, the original value of `release_conn` will be
# passed down into the recursive call, and its value will be respected.
#
# See issue #651 [1] for details.
#
# [1] <https://github.com/urllib3/urllib3/issues/651>
release_this_conn = release_conn

http_tunnel_required = connection_requires_http_tunnel(
self.proxy, self.proxy_config, destination_scheme
)

# Merge the proxy headers. Only done when not using HTTP CONNECT. We
# have to copy the headers dict so we can safely change it without those
# changes being reflected in anyone else's copy.
if not http_tunnel_required:
headers = headers.copy() # type: ignore[attr-defined]
headers.update(self.proxy_headers) # type: ignore[union-attr]

# Must keep the exception bound to a separate variable or else Python 3
# complains about UnboundLocalError.
err = None

# Keep track of whether we cleanly exited the except block. This
# ensures we do proper cleanup in finally.
clean_exit = False

# Rewind body position, if needed. Record current position
# for future rewinds in the event of a redirect/retry.
body_pos = set_file_position(body, body_pos)

try:
# Request a connection from the queue.
timeout_obj = self._get_timeout(timeout)
conn = self._get_conn(timeout=pool_timeout)

conn.timeout = timeout_obj.connect_timeout # type: ignore[assignment]

# Is this a closed/new connection that requires CONNECT tunnelling?
if self.proxy is not None and http_tunnel_required and conn.is_closed:
try:
self._prepare_proxy(conn)
except (BaseSSLError, OSError, SocketTimeout) as e:
self._raise_timeout(
err=e, url=self.proxy.url, timeout_value=conn.timeout
)
raise

# If we're going to release the connection in ``finally:``, then
# the response doesn't need to know about the connection. Otherwise
# it will also try to release it and we'll have a double-release
# mess.
response_conn = conn if not release_conn else None

# Make the request on the HTTPConnection object
> response = self._make_request(
conn,
method,
url,
timeout=timeout_obj,
body=body,
headers=headers,
chunked=chunked,
retries=retries,
response_conn=response_conn,
preload_content=preload_content,
decode_content=decode_content,
**response_kw,
)

venv/lib/python3.11/site-packages/urllib3/connectionpool.py:789:
_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _
venv/lib/python3.11/site-packages/urllib3/connectionpool.py:490: in _make_request
raise new_e
venv/lib/python3.11/site-packages/urllib3/connectionpool.py:466: in _make_request
self._validate_conn(conn)
venv/lib/python3.11/site-packages/urllib3/connectionpool.py:1095: in _validate_conn
conn.connect()
venv/lib/python3.11/site-packages/urllib3/connection.py:615: in connect
self.sock = sock = self._new_conn()
_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _

self = <urllib3.connection.HTTPSConnection object at 0x104015090>

def _new_conn(self) -> socket.socket:
"""Establish a socket connection and set nodelay settings on it.

:return: New socket connection.
"""
try:
sock = connection.create_connection(
(self._dns_host, self.port),
self.timeout,
source_address=self.source_address,
socket_options=self.socket_options,
)
except socket.gaierror as e:
> raise NameResolutionError(self.host, self, e) from e
E urllib3.exceptions.NameResolutionError: <urllib3.connection.HTTPSConnection object at 0x104015090>: Failed to resolve 'addons.allizom.org' ([Errno 8] nodename nor servname provided, or not known)

venv/lib/python3.11/site-packages/urllib3/connection.py:203: NameResolutionError

The above exception was the direct cause of the following exception:

self = <requests.adapters.HTTPAdapter object at 0x104015750>, request = <PreparedRequest [POST]>, stream = False, timeout = Timeout(connect=None, read=None, total=None), verify = True, cert = None
proxies = OrderedDict()

def send(
self, request, stream=False, timeout=None, verify=True, cert=None, proxies=None
):
"""Sends PreparedRequest object. Returns Response object.

:param request: The :class:`PreparedRequest <PreparedRequest>` being sent.
:param stream: (optional) Whether to stream the request content.
:param timeout: (optional) How long to wait for the server to send
data before giving up, as a float, or a :ref:`(connect timeout,
read timeout) <timeouts>` tuple.
:type timeout: float or tuple or urllib3 Timeout object
:param verify: (optional) Either a boolean, in which case it controls whether
we verify the server's TLS certificate, or a string, in which case it
must be a path to a CA bundle to use
:param cert: (optional) Any user-provided SSL certificate to be trusted.
:param proxies: (optional) The proxies dictionary to apply to the request.
:rtype: requests.Response
"""

try:
conn = self._get_connection(request, verify, proxies=proxies, cert=cert)
except LocationValueError as e:
raise InvalidURL(e, request=request)

self.cert_verify(conn, request.url, verify, cert)
url = self.request_url(request, proxies)
self.add_headers(
request,
stream=stream,
timeout=timeout,
verify=verify,
cert=cert,
proxies=proxies,
)

chunked = not (request.body is None or "Content-Length" in request.headers)

if isinstance(timeout, tuple):
try:
connect, read = timeout
timeout = TimeoutSauce(connect=connect, read=read)
except ValueError:
raise ValueError(
f"Invalid timeout {timeout}. Pass a (connect, read) timeout tuple, "
f"or a single float to set both timeouts to the same value."
)
elif isinstance(timeout, TimeoutSauce):
pass
else:
timeout = TimeoutSauce(connect=timeout, read=timeout)

try:
> resp = conn.urlopen(
method=request.method,
url=url,
body=request.body,
headers=request.headers,
redirect=False,
assert_same_host=False,
preload_content=False,
decode_content=False,
retries=self.max_retries,
timeout=timeout,
chunked=chunked,
)

venv/lib/python3.11/site-packages/requests/adapters.py:564:
_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _
venv/lib/python3.11/site-packages/urllib3/connectionpool.py:843: in urlopen
retries = retries.increment(
_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _

self = Retry(total=0, connect=None, read=False, redirect=None, status=None), method = 'POST', url = '/api/v5/addons/upload/', response = None
error = NameResolutionError("<urllib3.connection.HTTPSConnection object at 0x104015090>: Failed to resolve 'addons.allizom.org' ([Errno 8] nodename nor servname provided, or not known)")
_pool = <urllib3.connectionpool.HTTPSConnectionPool object at 0x104015250>, _stacktrace = <traceback object at 0x104015140>

def increment(
self,
method: str | None = None,
url: str | None = None,
response: BaseHTTPResponse | None = None,
error: Exception | None = None,
_pool: ConnectionPool | None = None,
_stacktrace: TracebackType | None = None,
) -> Self:
"""Return a new Retry object with incremented retry counters.

:param response: A response object, or None, if the server did not
return a response.
:type response: :class:`~urllib3.response.BaseHTTPResponse`
:param Exception error: An error encountered during the request, or
None if the response was received successfully.

:return: A new ``Retry`` object.
"""
if self.total is False and error:
# Disabled, indicate to re-raise the error.
raise reraise(type(error), error, _stacktrace)

total = self.total
if total is not None:
total -= 1

connect = self.connect
read = self.read
redirect = self.redirect
status_count = self.status
other = self.other
cause = "unknown"
status = None
redirect_location = None

if error and self._is_connection_error(error):
# Connect retry?
if connect is False:
raise reraise(type(error), error, _stacktrace)
elif connect is not None:
connect -= 1

elif error and self._is_read_error(error):
# Read retry?
if read is False or method is None or not self._is_method_retryable(method):
raise reraise(type(error), error, _stacktrace)
elif read is not None:
read -= 1

elif error:
# Other retry?
if other is not None:
other -= 1

elif response and response.get_redirect_location():
# Redirect retry?
if redirect is not None:
redirect -= 1
cause = "too many redirects"
response_redirect_location = response.get_redirect_location()
if response_redirect_location:
redirect_location = response_redirect_location
status = response.status

else:
# Incrementing because of a server error like a 500 in
# status_forcelist and the given method is in the allowed_methods
cause = ResponseError.GENERIC_ERROR
if response and response.status:
if status_count is not None:
status_count -= 1
cause = ResponseError.SPECIFIC_ERROR.format(status_code=response.status)
status = response.status

history = self.history + (
RequestHistory(method, url, error, status, redirect_location),
)

new_retry = self.new(
total=total,
connect=connect,
read=read,
redirect=redirect,
status=status_count,
other=other,
history=history,
)

if new_retry.is_exhausted():
reason = error or ResponseError(cause)
> raise MaxRetryError(_pool, url, reason) from reason # type: ignore[arg-type]
E urllib3.exceptions.MaxRetryError: HTTPSConnectionPool(host='addons.allizom.org', port=443): Max retries exceeded with url: /api/v5/addons/upload/ (Caused by NameResolutionError("<urllib3.connection.HTTPSConnection object at 0x104015090>: Failed to resolve 'addons.allizom.org' ([Errno 8] nodename nor servname provided, or not known)"))

venv/lib/python3.11/site-packages/urllib3/util/retry.py:519: MaxRetryError

During handling of the above exception, another exception occurred:

base_url = 'https://addons.allizom.org', session_auth = 'ldvd5ag27bkfpukx6rn2lcj0yuvakt3v'

@pytest.mark.serial
@pytest.mark.create_session("api_user")
def test_upload_unlisted_extension(base_url, session_auth):
with open("sample-addons/unlisted-addon.zip", "rb") as file:
> upload = requests.post(
url=f"{base_url}{_upload}",
headers={"Authorization": f"Session {session_auth}"},
files={"upload": file},
data={"channel": "unlisted"},
)

tests/api_w/test_addon_uploads.py:218:
_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _
venv/lib/python3.11/site-packages/requests/api.py:115: in post
return request("post", url, data=data, json=json, **kwargs)
venv/lib/python3.11/site-packages/requests/api.py:59: in request
return session.request(method=method, url=url, **kwargs)
venv/lib/python3.11/site-packages/requests/sessions.py:589: in request
resp = self.send(prep, **send_kwargs)
venv/lib/python3.11/site-packages/requests/sessions.py:703: in send
r = adapter.send(request, **kwargs)
_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _

self = <requests.adapters.HTTPAdapter object at 0x104015750>, request = <PreparedRequest [POST]>, stream = False, timeout = Timeout(connect=None, read=None, total=None), verify = True, cert = None
proxies = OrderedDict()

def send(
self, request, stream=False, timeout=None, verify=True, cert=None, proxies=None
):
"""Sends PreparedRequest object. Returns Response object.

:param request: The :class:`PreparedRequest <PreparedRequest>` being sent.
:param stream: (optional) Whether to stream the request content.
:param timeout: (optional) How long to wait for the server to send
data before giving up, as a float, or a :ref:`(connect timeout,
read timeout) <timeouts>` tuple.
:type timeout: float or tuple or urllib3 Timeout object
:param verify: (optional) Either a boolean, in which case it controls whether
we verify the server's TLS certificate, or a string, in which case it
must be a path to a CA bundle to use
:param cert: (optional) Any user-provided SSL certificate to be trusted.
:param proxies: (optional) The proxies dictionary to apply to the request.
:rtype: requests.Response
"""

try:
conn = self._get_connection(request, verify, proxies=proxies, cert=cert)
except LocationValueError as e:
raise InvalidURL(e, request=request)

self.cert_verify(conn, request.url, verify, cert)
url = self.request_url(request, proxies)
self.add_headers(
request,
stream=stream,
timeout=timeout,
verify=verify,
cert=cert,
proxies=proxies,
)

chunked = not (request.body is None or "Content-Length" in request.headers)

if isinstance(timeout, tuple):
try:
connect, read = timeout
timeout = TimeoutSauce(connect=connect, read=read)
except ValueError:
raise ValueError(
f"Invalid timeout {timeout}. Pass a (connect, read) timeout tuple, "
f"or a single float to set both timeouts to the same value."
)
elif isinstance(timeout, TimeoutSauce):
pass
else:
timeout = TimeoutSauce(connect=timeout, read=timeout)

try:
resp = conn.urlopen(
method=request.method,
url=url,
body=request.body,
headers=request.headers,
redirect=False,
assert_same_host=False,
preload_content=False,
decode_content=False,
retries=self.max_retries,
timeout=timeout,
chunked=chunked,
)

except (ProtocolError, OSError) as err:
raise ConnectionError(err, request=request)

except MaxRetryError as e:
if isinstance(e.reason, ConnectTimeoutError):
# TODO: Remove this in 3.0.0: see #2811
if not isinstance(e.reason, NewConnectionError):
raise ConnectTimeout(e, request=request)

if isinstance(e.reason, ResponseError):
raise RetryError(e, request=request)

if isinstance(e.reason, _ProxyError):
raise ProxyError(e, request=request)

if isinstance(e.reason, _SSLError):
# This branch is for urllib3 v1.22 and later.
raise SSLError(e, request=request)

> raise ConnectionError(e, request=request)
E requests.exceptions.ConnectionError: HTTPSConnectionPool(host='addons.allizom.org', port=443): Max retries exceeded with url: /api/v5/addons/upload/ (Caused by NameResolutionError("<urllib3.connection.HTTPSConnection object at 0x104015090>: Failed to resolve 'addons.allizom.org' ([Errno 8] nodename nor servname provided, or not known)"))

venv/lib/python3.11/site-packages/requests/adapters.py:597: ConnectionError
Failed tests/api_w/test_addon_uploads.py::test_submit_extension_with_invalid_uuid_format 0.00
self = <urllib3.connection.HTTPSConnection object at 0x10409a710>

def _new_conn(self) -> socket.socket:
"""Establish a socket connection and set nodelay settings on it.

:return: New socket connection.
"""
try:
> sock = connection.create_connection(
(self._dns_host, self.port),
self.timeout,
source_address=self.source_address,
socket_options=self.socket_options,
)

venv/lib/python3.11/site-packages/urllib3/connection.py:196:
_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _
venv/lib/python3.11/site-packages/urllib3/util/connection.py:60: in create_connection
for res in socket.getaddrinfo(host, port, family, socket.SOCK_STREAM):
_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _

host = 'addons.allizom.org', port = 443, family = <AddressFamily.AF_UNSPEC: 0>, type = <SocketKind.SOCK_STREAM: 1>, proto = 0, flags = 0

def getaddrinfo(host, port, family=0, type=0, proto=0, flags=0):
"""Resolve host and port into list of address info entries.

Translate the host/port argument into a sequence of 5-tuples that contain
all the necessary arguments for creating a socket connected to that service.
host is a domain name, a string representation of an IPv4/v6 address or
None. port is a string service name such as 'http', a numeric port number or
None. By passing None as the value of host and port, you can pass NULL to
the underlying C API.

The family, type and proto arguments can be optionally specified in order to
narrow the list of addresses returned. Passing zero as a value for each of
these arguments selects the full range of results.
"""
# We override this function since we want to translate the numeric family
# and socket type values to enum constants.
addrlist = []
> for res in _socket.getaddrinfo(host, port, family, type, proto, flags):
E socket.gaierror: [Errno 8] nodename nor servname provided, or not known

/Library/Frameworks/Python.framework/Versions/3.11/lib/python3.11/socket.py:962: gaierror

The above exception was the direct cause of the following exception:

self = <urllib3.connectionpool.HTTPSConnectionPool object at 0x104099e90>, method = 'POST', url = '/api/v5/addons/addon/', body = '{"version": {"upload": "some-invalid-uuid"}}'
headers = {'User-Agent': 'python-requests/2.32.0', 'Accept-Encoding': 'gzip, deflate', 'Accept': '*/*', 'Connection': 'keep-aliv...Authorization': 'Session ldvd5ag27bkfpukx6rn2lcj0yuvakt3v', 'Content-Type': 'application/json', 'Content-Length': '44'}
retries = Retry(total=0, connect=None, read=False, redirect=None, status=None), redirect = False, assert_same_host = False, timeout = Timeout(connect=None, read=None, total=None), pool_timeout = None
release_conn = False, chunked = False, body_pos = None, preload_content = False, decode_content = False, response_kw = {}
parsed_url = Url(scheme=None, auth=None, host=None, port=None, path='/api/v5/addons/addon/', query=None, fragment=None), destination_scheme = None, conn = None, release_this_conn = True
http_tunnel_required = False, err = None, clean_exit = False

def urlopen( # type: ignore[override]
self,
method: str,
url: str,
body: _TYPE_BODY | None = None,
headers: typing.Mapping[str, str] | None = None,
retries: Retry | bool | int | None = None,
redirect: bool = True,
assert_same_host: bool = True,
timeout: _TYPE_TIMEOUT = _DEFAULT_TIMEOUT,
pool_timeout: int | None = None,
release_conn: bool | None = None,
chunked: bool = False,
body_pos: _TYPE_BODY_POSITION | None = None,
preload_content: bool = True,
decode_content: bool = True,
**response_kw: typing.Any,
) -> BaseHTTPResponse:
"""
Get a connection from the pool and perform an HTTP request. This is the
lowest level call for making a request, so you'll need to specify all
the raw details.

.. note::

More commonly, it's appropriate to use a convenience method
such as :meth:`request`.

.. note::

`release_conn` will only behave as expected if
`preload_content=False` because we want to make
`preload_content=False` the default behaviour someday soon without
breaking backwards compatibility.

:param method:
HTTP request method (such as GET, POST, PUT, etc.)

:param url:
The URL to perform the request on.

:param body:
Data to send in the request body, either :class:`str`, :class:`bytes`,
an iterable of :class:`str`/:class:`bytes`, or a file-like object.

:param headers:
Dictionary of custom headers to send, such as User-Agent,
If-None-Match, etc. If None, pool headers are used. If provided,
these headers completely replace any pool-specific headers.

:param retries:
Configure the number of retries to allow before raising a
:class:`~urllib3.exceptions.MaxRetryError` exception.

If ``None`` (default) will retry 3 times, see ``Retry.DEFAULT``. Pass a
:class:`~urllib3.util.retry.Retry` object for fine-grained control
over different types of retries.
Pass an integer number to retry connection errors that many times,
but no other types of errors. Pass zero to never retry.

If ``False``, then retries are disabled and any exception is raised
immediately. Also, instead of raising a MaxRetryError on redirects,
the redirect response will be returned.

:type retries: :class:`~urllib3.util.retry.Retry`, False, or an int.

:param redirect:
If True, automatically handle redirects (status codes 301, 302,
303, 307, 308). Each redirect counts as a retry. Disabling retries
will disable redirect, too.

:param assert_same_host:
If ``True``, will make sure that the host of the pool requests is
consistent else will raise HostChangedError. When ``False``, you can
use the pool on an HTTP proxy and request foreign hosts.

:param timeout:
If specified, overrides the default timeout for this one
request. It may be a float (in seconds) or an instance of
:class:`urllib3.util.Timeout`.

:param pool_timeout:
If set and the pool is set to block=True, then this method will
block for ``pool_timeout`` seconds and raise EmptyPoolError if no
connection is available within the time period.

:param bool preload_content:
If True, the response's body will be preloaded into memory.

:param bool decode_content:
If True, will attempt to decode the body based on the
'content-encoding' header.

:param release_conn:
If False, then the urlopen call will not release the connection
back into the pool once a response is received (but will release if
you read the entire contents of the response such as when
`preload_content=True`). This is useful if you're not preloading
the response's content immediately. You will need to call
``r.release_conn()`` on the response ``r`` to return the connection
back into the pool. If None, it takes the value of ``preload_content``
which defaults to ``True``.

:param bool chunked:
If True, urllib3 will send the body using chunked transfer
encoding. Otherwise, urllib3 will send the body using the standard
content-length form. Defaults to False.

:param int body_pos:
Position to seek to in file-like body in the event of a retry or
redirect. Typically this won't need to be set because urllib3 will
auto-populate the value when needed.
"""
parsed_url = parse_url(url)
destination_scheme = parsed_url.scheme

if headers is None:
headers = self.headers

if not isinstance(retries, Retry):
retries = Retry.from_int(retries, redirect=redirect, default=self.retries)

if release_conn is None:
release_conn = preload_content

# Check host
if assert_same_host and not self.is_same_host(url):
raise HostChangedError(self, url, retries)

# Ensure that the URL we're connecting to is properly encoded
if url.startswith("/"):
url = to_str(_encode_target(url))
else:
url = to_str(parsed_url.url)

conn = None

# Track whether `conn` needs to be released before
# returning/raising/recursing. Update this variable if necessary, and
# leave `release_conn` constant throughout the function. That way, if
# the function recurses, the original value of `release_conn` will be
# passed down into the recursive call, and its value will be respected.
#
# See issue #651 [1] for details.
#
# [1] <https://github.com/urllib3/urllib3/issues/651>
release_this_conn = release_conn

http_tunnel_required = connection_requires_http_tunnel(
self.proxy, self.proxy_config, destination_scheme
)

# Merge the proxy headers. Only done when not using HTTP CONNECT. We
# have to copy the headers dict so we can safely change it without those
# changes being reflected in anyone else's copy.
if not http_tunnel_required:
headers = headers.copy() # type: ignore[attr-defined]
headers.update(self.proxy_headers) # type: ignore[union-attr]

# Must keep the exception bound to a separate variable or else Python 3
# complains about UnboundLocalError.
err = None

# Keep track of whether we cleanly exited the except block. This
# ensures we do proper cleanup in finally.
clean_exit = False

# Rewind body position, if needed. Record current position
# for future rewinds in the event of a redirect/retry.
body_pos = set_file_position(body, body_pos)

try:
# Request a connection from the queue.
timeout_obj = self._get_timeout(timeout)
conn = self._get_conn(timeout=pool_timeout)

conn.timeout = timeout_obj.connect_timeout # type: ignore[assignment]

# Is this a closed/new connection that requires CONNECT tunnelling?
if self.proxy is not None and http_tunnel_required and conn.is_closed:
try:
self._prepare_proxy(conn)
except (BaseSSLError, OSError, SocketTimeout) as e:
self._raise_timeout(
err=e, url=self.proxy.url, timeout_value=conn.timeout
)
raise

# If we're going to release the connection in ``finally:``, then
# the response doesn't need to know about the connection. Otherwise
# it will also try to release it and we'll have a double-release
# mess.
response_conn = conn if not release_conn else None

# Make the request on the HTTPConnection object
> response = self._make_request(
conn,
method,
url,
timeout=timeout_obj,
body=body,
headers=headers,
chunked=chunked,
retries=retries,
response_conn=response_conn,
preload_content=preload_content,
decode_content=decode_content,
**response_kw,
)

venv/lib/python3.11/site-packages/urllib3/connectionpool.py:789:
_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _
venv/lib/python3.11/site-packages/urllib3/connectionpool.py:490: in _make_request
raise new_e
venv/lib/python3.11/site-packages/urllib3/connectionpool.py:466: in _make_request
self._validate_conn(conn)
venv/lib/python3.11/site-packages/urllib3/connectionpool.py:1095: in _validate_conn
conn.connect()
venv/lib/python3.11/site-packages/urllib3/connection.py:615: in connect
self.sock = sock = self._new_conn()
_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _

self = <urllib3.connection.HTTPSConnection object at 0x10409a710>

def _new_conn(self) -> socket.socket:
"""Establish a socket connection and set nodelay settings on it.

:return: New socket connection.
"""
try:
sock = connection.create_connection(
(self._dns_host, self.port),
self.timeout,
source_address=self.source_address,
socket_options=self.socket_options,
)
except socket.gaierror as e:
> raise NameResolutionError(self.host, self, e) from e
E urllib3.exceptions.NameResolutionError: <urllib3.connection.HTTPSConnection object at 0x10409a710>: Failed to resolve 'addons.allizom.org' ([Errno 8] nodename nor servname provided, or not known)

venv/lib/python3.11/site-packages/urllib3/connection.py:203: NameResolutionError

The above exception was the direct cause of the following exception:

self = <requests.adapters.HTTPAdapter object at 0x104099190>, request = <PreparedRequest [POST]>, stream = False, timeout = Timeout(connect=None, read=None, total=None), verify = True, cert = None
proxies = OrderedDict()

def send(
self, request, stream=False, timeout=None, verify=True, cert=None, proxies=None
):
"""Sends PreparedRequest object. Returns Response object.

:param request: The :class:`PreparedRequest <PreparedRequest>` being sent.
:param stream: (optional) Whether to stream the request content.
:param timeout: (optional) How long to wait for the server to send
data before giving up, as a float, or a :ref:`(connect timeout,
read timeout) <timeouts>` tuple.
:type timeout: float or tuple or urllib3 Timeout object
:param verify: (optional) Either a boolean, in which case it controls whether
we verify the server's TLS certificate, or a string, in which case it
must be a path to a CA bundle to use
:param cert: (optional) Any user-provided SSL certificate to be trusted.
:param proxies: (optional) The proxies dictionary to apply to the request.
:rtype: requests.Response
"""

try:
conn = self._get_connection(request, verify, proxies=proxies, cert=cert)
except LocationValueError as e:
raise InvalidURL(e, request=request)

self.cert_verify(conn, request.url, verify, cert)
url = self.request_url(request, proxies)
self.add_headers(
request,
stream=stream,
timeout=timeout,
verify=verify,
cert=cert,
proxies=proxies,
)

chunked = not (request.body is None or "Content-Length" in request.headers)

if isinstance(timeout, tuple):
try:
connect, read = timeout
timeout = TimeoutSauce(connect=connect, read=read)
except ValueError:
raise ValueError(
f"Invalid timeout {timeout}. Pass a (connect, read) timeout tuple, "
f"or a single float to set both timeouts to the same value."
)
elif isinstance(timeout, TimeoutSauce):
pass
else:
timeout = TimeoutSauce(connect=timeout, read=timeout)

try:
> resp = conn.urlopen(
method=request.method,
url=url,
body=request.body,
headers=request.headers,
redirect=False,
assert_same_host=False,
preload_content=False,
decode_content=False,
retries=self.max_retries,
timeout=timeout,
chunked=chunked,
)

venv/lib/python3.11/site-packages/requests/adapters.py:564:
_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _
venv/lib/python3.11/site-packages/urllib3/connectionpool.py:843: in urlopen
retries = retries.increment(
_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _

self = Retry(total=0, connect=None, read=False, redirect=None, status=None), method = 'POST', url = '/api/v5/addons/addon/', response = None
error = NameResolutionError("<urllib3.connection.HTTPSConnection object at 0x10409a710>: Failed to resolve 'addons.allizom.org' ([Errno 8] nodename nor servname provided, or not known)")
_pool = <urllib3.connectionpool.HTTPSConnectionPool object at 0x104099e90>, _stacktrace = <traceback object at 0x10409a280>

def increment(
self,
method: str | None = None,
url: str | None = None,
response: BaseHTTPResponse | None = None,
error: Exception | None = None,
_pool: ConnectionPool | None = None,
_stacktrace: TracebackType | None = None,
) -> Self:
"""Return a new Retry object with incremented retry counters.

:param response: A response object, or None, if the server did not
return a response.
:type response: :class:`~urllib3.response.BaseHTTPResponse`
:param Exception error: An error encountered during the request, or
None if the response was received successfully.

:return: A new ``Retry`` object.
"""
if self.total is False and error:
# Disabled, indicate to re-raise the error.
raise reraise(type(error), error, _stacktrace)

total = self.total
if total is not None:
total -= 1

connect = self.connect
read = self.read
redirect = self.redirect
status_count = self.status
other = self.other
cause = "unknown"
status = None
redirect_location = None

if error and self._is_connection_error(error):
# Connect retry?
if connect is False:
raise reraise(type(error), error, _stacktrace)
elif connect is not None:
connect -= 1

elif error and self._is_read_error(error):
# Read retry?
if read is False or method is None or not self._is_method_retryable(method):
raise reraise(type(error), error, _stacktrace)
elif read is not None:
read -= 1

elif error:
# Other retry?
if other is not None:
other -= 1

elif response and response.get_redirect_location():
# Redirect retry?
if redirect is not None:
redirect -= 1
cause = "too many redirects"
response_redirect_location = response.get_redirect_location()
if response_redirect_location:
redirect_location = response_redirect_location
status = response.status

else:
# Incrementing because of a server error like a 500 in
# status_forcelist and the given method is in the allowed_methods
cause = ResponseError.GENERIC_ERROR
if response and response.status:
if status_count is not None:
status_count -= 1
cause = ResponseError.SPECIFIC_ERROR.format(status_code=response.status)
status = response.status

history = self.history + (
RequestHistory(method, url, error, status, redirect_location),
)

new_retry = self.new(
total=total,
connect=connect,
read=read,
redirect=redirect,
status=status_count,
other=other,
history=history,
)

if new_retry.is_exhausted():
reason = error or ResponseError(cause)
> raise MaxRetryError(_pool, url, reason) from reason # type: ignore[arg-type]
E urllib3.exceptions.MaxRetryError: HTTPSConnectionPool(host='addons.allizom.org', port=443): Max retries exceeded with url: /api/v5/addons/addon/ (Caused by NameResolutionError("<urllib3.connection.HTTPSConnection object at 0x10409a710>: Failed to resolve 'addons.allizom.org' ([Errno 8] nodename nor servname provided, or not known)"))

venv/lib/python3.11/site-packages/urllib3/util/retry.py:519: MaxRetryError

During handling of the above exception, another exception occurred:

base_url = 'https://addons.allizom.org', session_auth = 'ldvd5ag27bkfpukx6rn2lcj0yuvakt3v'

@pytest.mark.serial
@pytest.mark.create_session("api_user")
def test_submit_extension_with_invalid_uuid_format(base_url, session_auth):
"""The UUID format doesn't match the expected format for the uuid value"""
uuid = [
"some-invalid-uuid",
{"upload": "d4ce752a971b4a5aafcd175122726431"},
None,
"",
]
for item in uuid:
data = {"version": {"upload": item}}
> create_addon = requests.post(
url=f"{base_url}{_addon_create}",
headers={
"Authorization": f"Session {session_auth}",
"Content-Type": "application/json",
},
data=json.dumps(data),
)

tests/api_w/test_addon_uploads.py:264:
_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _
venv/lib/python3.11/site-packages/requests/api.py:115: in post
return request("post", url, data=data, json=json, **kwargs)
venv/lib/python3.11/site-packages/requests/api.py:59: in request
return session.request(method=method, url=url, **kwargs)
venv/lib/python3.11/site-packages/requests/sessions.py:589: in request
resp = self.send(prep, **send_kwargs)
venv/lib/python3.11/site-packages/requests/sessions.py:703: in send
r = adapter.send(request, **kwargs)
_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _

self = <requests.adapters.HTTPAdapter object at 0x104099190>, request = <PreparedRequest [POST]>, stream = False, timeout = Timeout(connect=None, read=None, total=None), verify = True, cert = None
proxies = OrderedDict()

def send(
self, request, stream=False, timeout=None, verify=True, cert=None, proxies=None
):
"""Sends PreparedRequest object. Returns Response object.

:param request: The :class:`PreparedRequest <PreparedRequest>` being sent.
:param stream: (optional) Whether to stream the request content.
:param timeout: (optional) How long to wait for the server to send
data before giving up, as a float, or a :ref:`(connect timeout,
read timeout) <timeouts>` tuple.
:type timeout: float or tuple or urllib3 Timeout object
:param verify: (optional) Either a boolean, in which case it controls whether
we verify the server's TLS certificate, or a string, in which case it
must be a path to a CA bundle to use
:param cert: (optional) Any user-provided SSL certificate to be trusted.
:param proxies: (optional) The proxies dictionary to apply to the request.
:rtype: requests.Response
"""

try:
conn = self._get_connection(request, verify, proxies=proxies, cert=cert)
except LocationValueError as e:
raise InvalidURL(e, request=request)

self.cert_verify(conn, request.url, verify, cert)
url = self.request_url(request, proxies)
self.add_headers(
request,
stream=stream,
timeout=timeout,
verify=verify,
cert=cert,
proxies=proxies,
)

chunked = not (request.body is None or "Content-Length" in request.headers)

if isinstance(timeout, tuple):
try:
connect, read = timeout
timeout = TimeoutSauce(connect=connect, read=read)
except ValueError:
raise ValueError(
f"Invalid timeout {timeout}. Pass a (connect, read) timeout tuple, "
f"or a single float to set both timeouts to the same value."
)
elif isinstance(timeout, TimeoutSauce):
pass
else:
timeout = TimeoutSauce(connect=timeout, read=timeout)

try:
resp = conn.urlopen(
method=request.method,
url=url,
body=request.body,
headers=request.headers,
redirect=False,
assert_same_host=False,
preload_content=False,
decode_content=False,
retries=self.max_retries,
timeout=timeout,
chunked=chunked,
)

except (ProtocolError, OSError) as err:
raise ConnectionError(err, request=request)

except MaxRetryError as e:
if isinstance(e.reason, ConnectTimeoutError):
# TODO: Remove this in 3.0.0: see #2811
if not isinstance(e.reason, NewConnectionError):
raise ConnectTimeout(e, request=request)

if isinstance(e.reason, ResponseError):
raise RetryError(e, request=request)

if isinstance(e.reason, _ProxyError):
raise ProxyError(e, request=request)

if isinstance(e.reason, _SSLError):
# This branch is for urllib3 v1.22 and later.
raise SSLError(e, request=request)

> raise ConnectionError(e, request=request)
E requests.exceptions.ConnectionError: HTTPSConnectionPool(host='addons.allizom.org', port=443): Max retries exceeded with url: /api/v5/addons/addon/ (Caused by NameResolutionError("<urllib3.connection.HTTPSConnection object at 0x10409a710>: Failed to resolve 'addons.allizom.org' ([Errno 8] nodename nor servname provided, or not known)"))

venv/lib/python3.11/site-packages/requests/adapters.py:597: ConnectionError
Failed tests/api_w/test_addon_uploads.py::test_submit_extension_with_incorrect_uuid 0.01
self = <urllib3.connection.HTTPSConnection object at 0x103f28590>

def _new_conn(self) -> socket.socket:
"""Establish a socket connection and set nodelay settings on it.

:return: New socket connection.
"""
try:
> sock = connection.create_connection(
(self._dns_host, self.port),
self.timeout,
source_address=self.source_address,
socket_options=self.socket_options,
)

venv/lib/python3.11/site-packages/urllib3/connection.py:196:
_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _
venv/lib/python3.11/site-packages/urllib3/util/connection.py:60: in create_connection
for res in socket.getaddrinfo(host, port, family, socket.SOCK_STREAM):
_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _

host = 'addons.allizom.org', port = 443, family = <AddressFamily.AF_UNSPEC: 0>, type = <SocketKind.SOCK_STREAM: 1>, proto = 0, flags = 0

def getaddrinfo(host, port, family=0, type=0, proto=0, flags=0):
"""Resolve host and port into list of address info entries.

Translate the host/port argument into a sequence of 5-tuples that contain
all the necessary arguments for creating a socket connected to that service.
host is a domain name, a string representation of an IPv4/v6 address or
None. port is a string service name such as 'http', a numeric port number or
None. By passing None as the value of host and port, you can pass NULL to
the underlying C API.

The family, type and proto arguments can be optionally specified in order to
narrow the list of addresses returned. Passing zero as a value for each of
these arguments selects the full range of results.
"""
# We override this function since we want to translate the numeric family
# and socket type values to enum constants.
addrlist = []
> for res in _socket.getaddrinfo(host, port, family, type, proto, flags):
E socket.gaierror: [Errno 8] nodename nor servname provided, or not known

/Library/Frameworks/Python.framework/Versions/3.11/lib/python3.11/socket.py:962: gaierror

The above exception was the direct cause of the following exception:

self = <urllib3.connectionpool.HTTPSConnectionPool object at 0x103f28290>, method = 'POST', url = '/api/v5/addons/addon/', body = '{"version": {"upload": "d4ce752a971b4a5aafcd175122726431"}}'
headers = {'User-Agent': 'python-requests/2.32.0', 'Accept-Encoding': 'gzip, deflate', 'Accept': '*/*', 'Connection': 'keep-aliv...Authorization': 'Session ldvd5ag27bkfpukx6rn2lcj0yuvakt3v', 'Content-Type': 'application/json', 'Content-Length': '59'}
retries = Retry(total=0, connect=None, read=False, redirect=None, status=None), redirect = False, assert_same_host = False, timeout = Timeout(connect=None, read=None, total=None), pool_timeout = None
release_conn = False, chunked = False, body_pos = None, preload_content = False, decode_content = False, response_kw = {}
parsed_url = Url(scheme=None, auth=None, host=None, port=None, path='/api/v5/addons/addon/', query=None, fragment=None), destination_scheme = None, conn = None, release_this_conn = True
http_tunnel_required = False, err = None, clean_exit = False

def urlopen( # type: ignore[override]
self,
method: str,
url: str,
body: _TYPE_BODY | None = None,
headers: typing.Mapping[str, str] | None = None,
retries: Retry | bool | int | None = None,
redirect: bool = True,
assert_same_host: bool = True,
timeout: _TYPE_TIMEOUT = _DEFAULT_TIMEOUT,
pool_timeout: int | None = None,
release_conn: bool | None = None,
chunked: bool = False,
body_pos: _TYPE_BODY_POSITION | None = None,
preload_content: bool = True,
decode_content: bool = True,
**response_kw: typing.Any,
) -> BaseHTTPResponse:
"""
Get a connection from the pool and perform an HTTP request. This is the
lowest level call for making a request, so you'll need to specify all
the raw details.

.. note::

More commonly, it's appropriate to use a convenience method
such as :meth:`request`.

.. note::

`release_conn` will only behave as expected if
`preload_content=False` because we want to make
`preload_content=False` the default behaviour someday soon without
breaking backwards compatibility.

:param method:
HTTP request method (such as GET, POST, PUT, etc.)

:param url:
The URL to perform the request on.

:param body:
Data to send in the request body, either :class:`str`, :class:`bytes`,
an iterable of :class:`str`/:class:`bytes`, or a file-like object.

:param headers:
Dictionary of custom headers to send, such as User-Agent,
If-None-Match, etc. If None, pool headers are used. If provided,
these headers completely replace any pool-specific headers.

:param retries:
Configure the number of retries to allow before raising a
:class:`~urllib3.exceptions.MaxRetryError` exception.

If ``None`` (default) will retry 3 times, see ``Retry.DEFAULT``. Pass a
:class:`~urllib3.util.retry.Retry` object for fine-grained control
over different types of retries.
Pass an integer number to retry connection errors that many times,
but no other types of errors. Pass zero to never retry.

If ``False``, then retries are disabled and any exception is raised
immediately. Also, instead of raising a MaxRetryError on redirects,
the redirect response will be returned.

:type retries: :class:`~urllib3.util.retry.Retry`, False, or an int.

:param redirect:
If True, automatically handle redirects (status codes 301, 302,
303, 307, 308). Each redirect counts as a retry. Disabling retries
will disable redirect, too.

:param assert_same_host:
If ``True``, will make sure that the host of the pool requests is
consistent else will raise HostChangedError. When ``False``, you can
use the pool on an HTTP proxy and request foreign hosts.

:param timeout:
If specified, overrides the default timeout for this one
request. It may be a float (in seconds) or an instance of
:class:`urllib3.util.Timeout`.

:param pool_timeout:
If set and the pool is set to block=True, then this method will
block for ``pool_timeout`` seconds and raise EmptyPoolError if no
connection is available within the time period.

:param bool preload_content:
If True, the response's body will be preloaded into memory.

:param bool decode_content:
If True, will attempt to decode the body based on the
'content-encoding' header.

:param release_conn:
If False, then the urlopen call will not release the connection
back into the pool once a response is received (but will release if
you read the entire contents of the response such as when
`preload_content=True`). This is useful if you're not preloading
the response's content immediately. You will need to call
``r.release_conn()`` on the response ``r`` to return the connection
back into the pool. If None, it takes the value of ``preload_content``
which defaults to ``True``.

:param bool chunked:
If True, urllib3 will send the body using chunked transfer
encoding. Otherwise, urllib3 will send the body using the standard
content-length form. Defaults to False.

:param int body_pos:
Position to seek to in file-like body in the event of a retry or
redirect. Typically this won't need to be set because urllib3 will
auto-populate the value when needed.
"""
parsed_url = parse_url(url)
destination_scheme = parsed_url.scheme

if headers is None:
headers = self.headers

if not isinstance(retries, Retry):
retries = Retry.from_int(retries, redirect=redirect, default=self.retries)

if release_conn is None:
release_conn = preload_content

# Check host
if assert_same_host and not self.is_same_host(url):
raise HostChangedError(self, url, retries)

# Ensure that the URL we're connecting to is properly encoded
if url.startswith("/"):
url = to_str(_encode_target(url))
else:
url = to_str(parsed_url.url)

conn = None

# Track whether `conn` needs to be released before
# returning/raising/recursing. Update this variable if necessary, and
# leave `release_conn` constant throughout the function. That way, if
# the function recurses, the original value of `release_conn` will be
# passed down into the recursive call, and its value will be respected.
#
# See issue #651 [1] for details.
#
# [1] <https://github.com/urllib3/urllib3/issues/651>
release_this_conn = release_conn

http_tunnel_required = connection_requires_http_tunnel(
self.proxy, self.proxy_config, destination_scheme
)

# Merge the proxy headers. Only done when not using HTTP CONNECT. We
# have to copy the headers dict so we can safely change it without those
# changes being reflected in anyone else's copy.
if not http_tunnel_required:
headers = headers.copy() # type: ignore[attr-defined]
headers.update(self.proxy_headers) # type: ignore[union-attr]

# Must keep the exception bound to a separate variable or else Python 3
# complains about UnboundLocalError.
err = None

# Keep track of whether we cleanly exited the except block. This
# ensures we do proper cleanup in finally.
clean_exit = False

# Rewind body position, if needed. Record current position
# for future rewinds in the event of a redirect/retry.
body_pos = set_file_position(body, body_pos)

try:
# Request a connection from the queue.
timeout_obj = self._get_timeout(timeout)
conn = self._get_conn(timeout=pool_timeout)

conn.timeout = timeout_obj.connect_timeout # type: ignore[assignment]

# Is this a closed/new connection that requires CONNECT tunnelling?
if self.proxy is not None and http_tunnel_required and conn.is_closed:
try:
self._prepare_proxy(conn)
except (BaseSSLError, OSError, SocketTimeout) as e:
self._raise_timeout(
err=e, url=self.proxy.url, timeout_value=conn.timeout
)
raise

# If we're going to release the connection in ``finally:``, then
# the response doesn't need to know about the connection. Otherwise
# it will also try to release it and we'll have a double-release
# mess.
response_conn = conn if not release_conn else None

# Make the request on the HTTPConnection object
> response = self._make_request(
conn,
method,
url,
timeout=timeout_obj,
body=body,
headers=headers,
chunked=chunked,
retries=retries,
response_conn=response_conn,
preload_content=preload_content,
decode_content=decode_content,
**response_kw,
)

venv/lib/python3.11/site-packages/urllib3/connectionpool.py:789:
_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _
venv/lib/python3.11/site-packages/urllib3/connectionpool.py:490: in _make_request
raise new_e
venv/lib/python3.11/site-packages/urllib3/connectionpool.py:466: in _make_request
self._validate_conn(conn)
venv/lib/python3.11/site-packages/urllib3/connectionpool.py:1095: in _validate_conn
conn.connect()
venv/lib/python3.11/site-packages/urllib3/connection.py:615: in connect
self.sock = sock = self._new_conn()
_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _

self = <urllib3.connection.HTTPSConnection object at 0x103f28590>

def _new_conn(self) -> socket.socket:
"""Establish a socket connection and set nodelay settings on it.

:return: New socket connection.
"""
try:
sock = connection.create_connection(
(self._dns_host, self.port),
self.timeout,
source_address=self.source_address,
socket_options=self.socket_options,
)
except socket.gaierror as e:
> raise NameResolutionError(self.host, self, e) from e
E urllib3.exceptions.NameResolutionError: <urllib3.connection.HTTPSConnection object at 0x103f28590>: Failed to resolve 'addons.allizom.org' ([Errno 8] nodename nor servname provided, or not known)

venv/lib/python3.11/site-packages/urllib3/connection.py:203: NameResolutionError

The above exception was the direct cause of the following exception:

self = <requests.adapters.HTTPAdapter object at 0x103f2bf50>, request = <PreparedRequest [POST]>, stream = False, timeout = Timeout(connect=None, read=None, total=None), verify = True, cert = None
proxies = OrderedDict()

def send(
self, request, stream=False, timeout=None, verify=True, cert=None, proxies=None
):
"""Sends PreparedRequest object. Returns Response object.

:param request: The :class:`PreparedRequest <PreparedRequest>` being sent.
:param stream: (optional) Whether to stream the request content.
:param timeout: (optional) How long to wait for the server to send
data before giving up, as a float, or a :ref:`(connect timeout,
read timeout) <timeouts>` tuple.
:type timeout: float or tuple or urllib3 Timeout object
:param verify: (optional) Either a boolean, in which case it controls whether
we verify the server's TLS certificate, or a string, in which case it
must be a path to a CA bundle to use
:param cert: (optional) Any user-provided SSL certificate to be trusted.
:param proxies: (optional) The proxies dictionary to apply to the request.
:rtype: requests.Response
"""

try:
conn = self._get_connection(request, verify, proxies=proxies, cert=cert)
except LocationValueError as e:
raise InvalidURL(e, request=request)

self.cert_verify(conn, request.url, verify, cert)
url = self.request_url(request, proxies)
self.add_headers(
request,
stream=stream,
timeout=timeout,
verify=verify,
cert=cert,
proxies=proxies,
)

chunked = not (request.body is None or "Content-Length" in request.headers)

if isinstance(timeout, tuple):
try:
connect, read = timeout
timeout = TimeoutSauce(connect=connect, read=read)
except ValueError:
raise ValueError(
f"Invalid timeout {timeout}. Pass a (connect, read) timeout tuple, "
f"or a single float to set both timeouts to the same value."
)
elif isinstance(timeout, TimeoutSauce):
pass
else:
timeout = TimeoutSauce(connect=timeout, read=timeout)

try:
> resp = conn.urlopen(
method=request.method,
url=url,
body=request.body,
headers=request.headers,
redirect=False,
assert_same_host=False,
preload_content=False,
decode_content=False,
retries=self.max_retries,
timeout=timeout,
chunked=chunked,
)

venv/lib/python3.11/site-packages/requests/adapters.py:564:
_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _
venv/lib/python3.11/site-packages/urllib3/connectionpool.py:843: in urlopen
retries = retries.increment(
_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _

self = Retry(total=0, connect=None, read=False, redirect=None, status=None), method = 'POST', url = '/api/v5/addons/addon/', response = None
error = NameResolutionError("<urllib3.connection.HTTPSConnection object at 0x103f28590>: Failed to resolve 'addons.allizom.org' ([Errno 8] nodename nor servname provided, or not known)")
_pool = <urllib3.connectionpool.HTTPSConnectionPool object at 0x103f28290>, _stacktrace = <traceback object at 0x103f28800>

def increment(
self,
method: str | None = None,
url: str | None = None,
response: BaseHTTPResponse | None = None,
error: Exception | None = None,
_pool: ConnectionPool | None = None,
_stacktrace: TracebackType | None = None,
) -> Self:
"""Return a new Retry object with incremented retry counters.

:param response: A response object, or None, if the server did not
return a response.
:type response: :class:`~urllib3.response.BaseHTTPResponse`
:param Exception error: An error encountered during the request, or
None if the response was received successfully.

:return: A new ``Retry`` object.
"""
if self.total is False and error:
# Disabled, indicate to re-raise the error.
raise reraise(type(error), error, _stacktrace)

total = self.total
if total is not None:
total -= 1

connect = self.connect
read = self.read
redirect = self.redirect
status_count = self.status
other = self.other
cause = "unknown"
status = None
redirect_location = None

if error and self._is_connection_error(error):
# Connect retry?
if connect is False:
raise reraise(type(error), error, _stacktrace)
elif connect is not None:
connect -= 1

elif error and self._is_read_error(error):
# Read retry?
if read is False or method is None or not self._is_method_retryable(method):
raise reraise(type(error), error, _stacktrace)
elif read is not None:
read -= 1

elif error:
# Other retry?
if other is not None:
other -= 1

elif response and response.get_redirect_location():
# Redirect retry?
if redirect is not None:
redirect -= 1
cause = "too many redirects"
response_redirect_location = response.get_redirect_location()
if response_redirect_location:
redirect_location = response_redirect_location
status = response.status

else:
# Incrementing because of a server error like a 500 in
# status_forcelist and the given method is in the allowed_methods
cause = ResponseError.GENERIC_ERROR
if response and response.status:
if status_count is not None:
status_count -= 1
cause = ResponseError.SPECIFIC_ERROR.format(status_code=response.status)
status = response.status

history = self.history + (
RequestHistory(method, url, error, status, redirect_location),
)

new_retry = self.new(
total=total,
connect=connect,
read=read,
redirect=redirect,
status=status_count,
other=other,
history=history,
)

if new_retry.is_exhausted():
reason = error or ResponseError(cause)
> raise MaxRetryError(_pool, url, reason) from reason # type: ignore[arg-type]
E urllib3.exceptions.MaxRetryError: HTTPSConnectionPool(host='addons.allizom.org', port=443): Max retries exceeded with url: /api/v5/addons/addon/ (Caused by NameResolutionError("<urllib3.connection.HTTPSConnection object at 0x103f28590>: Failed to resolve 'addons.allizom.org' ([Errno 8] nodename nor servname provided, or not known)"))

venv/lib/python3.11/site-packages/urllib3/util/retry.py:519: MaxRetryError

During handling of the above exception, another exception occurred:

base_url = 'https://addons.allizom.org', session_auth = 'ldvd5ag27bkfpukx6rn2lcj0yuvakt3v'

@pytest.mark.serial
@pytest.mark.create_session("api_user")
def test_submit_extension_with_incorrect_uuid(base_url, session_auth):
"""The UUID format is accepted but there is no valid upload found for the given uuid"""
uuid = ["d4ce752a971b4a5aafcd175122726431", 12345]
for item in uuid:
data = {"version": {"upload": item}}
> create_addon = requests.post(
url=f"{base_url}{_addon_create}",
headers={
"Authorization": f"Session {session_auth}",
"Content-Type": "application/json",
},
data=json.dumps(data),
)

tests/api_w/test_addon_uploads.py:298:
_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _
venv/lib/python3.11/site-packages/requests/api.py:115: in post
return request("post", url, data=data, json=json, **kwargs)
venv/lib/python3.11/site-packages/requests/api.py:59: in request
return session.request(method=method, url=url, **kwargs)
venv/lib/python3.11/site-packages/requests/sessions.py:589: in request
resp = self.send(prep, **send_kwargs)
venv/lib/python3.11/site-packages/requests/sessions.py:703: in send
r = adapter.send(request, **kwargs)
_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _

self = <requests.adapters.HTTPAdapter object at 0x103f2bf50>, request = <PreparedRequest [POST]>, stream = False, timeout = Timeout(connect=None, read=None, total=None), verify = True, cert = None
proxies = OrderedDict()

def send(
self, request, stream=False, timeout=None, verify=True, cert=None, proxies=None
):
"""Sends PreparedRequest object. Returns Response object.

:param request: The :class:`PreparedRequest <PreparedRequest>` being sent.
:param stream: (optional) Whether to stream the request content.
:param timeout: (optional) How long to wait for the server to send
data before giving up, as a float, or a :ref:`(connect timeout,
read timeout) <timeouts>` tuple.
:type timeout: float or tuple or urllib3 Timeout object
:param verify: (optional) Either a boolean, in which case it controls whether
we verify the server's TLS certificate, or a string, in which case it
must be a path to a CA bundle to use
:param cert: (optional) Any user-provided SSL certificate to be trusted.
:param proxies: (optional) The proxies dictionary to apply to the request.
:rtype: requests.Response
"""

try:
conn = self._get_connection(request, verify, proxies=proxies, cert=cert)
except LocationValueError as e:
raise InvalidURL(e, request=request)

self.cert_verify(conn, request.url, verify, cert)
url = self.request_url(request, proxies)
self.add_headers(
request,
stream=stream,
timeout=timeout,
verify=verify,
cert=cert,
proxies=proxies,
)

chunked = not (request.body is None or "Content-Length" in request.headers)

if isinstance(timeout, tuple):
try:
connect, read = timeout
timeout = TimeoutSauce(connect=connect, read=read)
except ValueError:
raise ValueError(
f"Invalid timeout {timeout}. Pass a (connect, read) timeout tuple, "
f"or a single float to set both timeouts to the same value."
)
elif isinstance(timeout, TimeoutSauce):
pass
else:
timeout = TimeoutSauce(connect=timeout, read=timeout)

try:
resp = conn.urlopen(
method=request.method,
url=url,
body=request.body,
headers=request.headers,
redirect=False,
assert_same_host=False,
preload_content=False,
decode_content=False,
retries=self.max_retries,
timeout=timeout,
chunked=chunked,
)

except (ProtocolError, OSError) as err:
raise ConnectionError(err, request=request)

except MaxRetryError as e:
if isinstance(e.reason, ConnectTimeoutError):
# TODO: Remove this in 3.0.0: see #2811
if not isinstance(e.reason, NewConnectionError):
raise ConnectTimeout(e, request=request)

if isinstance(e.reason, ResponseError):
raise RetryError(e, request=request)

if isinstance(e.reason, _ProxyError):
raise ProxyError(e, request=request)

if isinstance(e.reason, _SSLError):
# This branch is for urllib3 v1.22 and later.
raise SSLError(e, request=request)

> raise ConnectionError(e, request=request)
E requests.exceptions.ConnectionError: HTTPSConnectionPool(host='addons.allizom.org', port=443): Max retries exceeded with url: /api/v5/addons/addon/ (Caused by NameResolutionError("<urllib3.connection.HTTPSConnection object at 0x103f28590>: Failed to resolve 'addons.allizom.org' ([Errno 8] nodename nor servname provided, or not known)"))

venv/lib/python3.11/site-packages/requests/adapters.py:597: ConnectionError
Failed tests/api_w/test_addon_uploads.py::test_submit_xpi_with_trademark_restricted_user[Firefox in addon name] 0.02
self = <urllib3.connection.HTTPSConnection object at 0x10418d650>

def _new_conn(self) -> socket.socket:
"""Establish a socket connection and set nodelay settings on it.

:return: New socket connection.
"""
try:
> sock = connection.create_connection(
(self._dns_host, self.port),
self.timeout,
source_address=self.source_address,
socket_options=self.socket_options,
)

venv/lib/python3.11/site-packages/urllib3/connection.py:196:
_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _
venv/lib/python3.11/site-packages/urllib3/util/connection.py:60: in create_connection
for res in socket.getaddrinfo(host, port, family, socket.SOCK_STREAM):
_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _

host = 'addons.allizom.org', port = 443, family = <AddressFamily.AF_UNSPEC: 0>, type = <SocketKind.SOCK_STREAM: 1>, proto = 0, flags = 0

def getaddrinfo(host, port, family=0, type=0, proto=0, flags=0):
"""Resolve host and port into list of address info entries.

Translate the host/port argument into a sequence of 5-tuples that contain
all the necessary arguments for creating a socket connected to that service.
host is a domain name, a string representation of an IPv4/v6 address or
None. port is a string service name such as 'http', a numeric port number or
None. By passing None as the value of host and port, you can pass NULL to
the underlying C API.

The family, type and proto arguments can be optionally specified in order to
narrow the list of addresses returned. Passing zero as a value for each of
these arguments selects the full range of results.
"""
# We override this function since we want to translate the numeric family
# and socket type values to enum constants.
addrlist = []
> for res in _socket.getaddrinfo(host, port, family, type, proto, flags):
E socket.gaierror: [Errno 8] nodename nor servname provided, or not known

/Library/Frameworks/Python.framework/Versions/3.11/lib/python3.11/socket.py:962: gaierror

The above exception was the direct cause of the following exception:

self = <urllib3.connectionpool.HTTPSConnectionPool object at 0x10418d2d0>, method = 'POST', url = '/api/v5/addons/upload/'
body = b'--da93320b276c71a06623b8af796dfec8\r\nContent-Disposition: form-data; name="channel"\r\n\r\nlisted\r\n--da93320b276c...\x05\x06\x00\x00\x00\x00\x01\x00\x01\x00;\x00\x00\x00u\x00\x00\x00\x00\x00\r\n--da93320b276c71a06623b8af796dfec8--\r\n'
headers = {'User-Agent': 'python-requests/2.32.0', 'Accept-Encoding': 'gzip, deflate', 'Accept': '*/*', 'Connection': 'keep-aliv...j0yuvakt3v', 'Content-Length': '444', 'Content-Type': 'multipart/form-data; boundary=da93320b276c71a06623b8af796dfec8'}
retries = Retry(total=0, connect=None, read=False, redirect=None, status=None), redirect = False, assert_same_host = False, timeout = Timeout(connect=None, read=None, total=None), pool_timeout = None
release_conn = False, chunked = False, body_pos = None, preload_content = False, decode_content = False, response_kw = {}
parsed_url = Url(scheme=None, auth=None, host=None, port=None, path='/api/v5/addons/upload/', query=None, fragment=None), destination_scheme = None, conn = None, release_this_conn = True
http_tunnel_required = False, err = None, clean_exit = False

def urlopen( # type: ignore[override]
self,
method: str,
url: str,
body: _TYPE_BODY | None = None,
headers: typing.Mapping[str, str] | None = None,
retries: Retry | bool | int | None = None,
redirect: bool = True,
assert_same_host: bool = True,
timeout: _TYPE_TIMEOUT = _DEFAULT_TIMEOUT,
pool_timeout: int | None = None,
release_conn: bool | None = None,
chunked: bool = False,
body_pos: _TYPE_BODY_POSITION | None = None,
preload_content: bool = True,
decode_content: bool = True,
**response_kw: typing.Any,
) -> BaseHTTPResponse:
"""
Get a connection from the pool and perform an HTTP request. This is the
lowest level call for making a request, so you'll need to specify all
the raw details.

.. note::

More commonly, it's appropriate to use a convenience method
such as :meth:`request`.

.. note::

`release_conn` will only behave as expected if
`preload_content=False` because we want to make
`preload_content=False` the default behaviour someday soon without
breaking backwards compatibility.

:param method:
HTTP request method (such as GET, POST, PUT, etc.)

:param url:
The URL to perform the request on.

:param body:
Data to send in the request body, either :class:`str`, :class:`bytes`,
an iterable of :class:`str`/:class:`bytes`, or a file-like object.

:param headers:
Dictionary of custom headers to send, such as User-Agent,
If-None-Match, etc. If None, pool headers are used. If provided,
these headers completely replace any pool-specific headers.

:param retries:
Configure the number of retries to allow before raising a
:class:`~urllib3.exceptions.MaxRetryError` exception.

If ``None`` (default) will retry 3 times, see ``Retry.DEFAULT``. Pass a
:class:`~urllib3.util.retry.Retry` object for fine-grained control
over different types of retries.
Pass an integer number to retry connection errors that many times,
but no other types of errors. Pass zero to never retry.

If ``False``, then retries are disabled and any exception is raised
immediately. Also, instead of raising a MaxRetryError on redirects,
the redirect response will be returned.

:type retries: :class:`~urllib3.util.retry.Retry`, False, or an int.

:param redirect:
If True, automatically handle redirects (status codes 301, 302,
303, 307, 308). Each redirect counts as a retry. Disabling retries
will disable redirect, too.

:param assert_same_host:
If ``True``, will make sure that the host of the pool requests is
consistent else will raise HostChangedError. When ``False``, you can
use the pool on an HTTP proxy and request foreign hosts.

:param timeout:
If specified, overrides the default timeout for this one
request. It may be a float (in seconds) or an instance of
:class:`urllib3.util.Timeout`.

:param pool_timeout:
If set and the pool is set to block=True, then this method will
block for ``pool_timeout`` seconds and raise EmptyPoolError if no
connection is available within the time period.

:param bool preload_content:
If True, the response's body will be preloaded into memory.

:param bool decode_content:
If True, will attempt to decode the body based on the
'content-encoding' header.

:param release_conn:
If False, then the urlopen call will not release the connection
back into the pool once a response is received (but will release if
you read the entire contents of the response such as when
`preload_content=True`). This is useful if you're not preloading
the response's content immediately. You will need to call
``r.release_conn()`` on the response ``r`` to return the connection
back into the pool. If None, it takes the value of ``preload_content``
which defaults to ``True``.

:param bool chunked:
If True, urllib3 will send the body using chunked transfer
encoding. Otherwise, urllib3 will send the body using the standard
content-length form. Defaults to False.

:param int body_pos:
Position to seek to in file-like body in the event of a retry or
redirect. Typically this won't need to be set because urllib3 will
auto-populate the value when needed.
"""
parsed_url = parse_url(url)
destination_scheme = parsed_url.scheme

if headers is None:
headers = self.headers

if not isinstance(retries, Retry):
retries = Retry.from_int(retries, redirect=redirect, default=self.retries)

if release_conn is None:
release_conn = preload_content

# Check host
if assert_same_host and not self.is_same_host(url):
raise HostChangedError(self, url, retries)

# Ensure that the URL we're connecting to is properly encoded
if url.startswith("/"):
url = to_str(_encode_target(url))
else:
url = to_str(parsed_url.url)

conn = None

# Track whether `conn` needs to be released before
# returning/raising/recursing. Update this variable if necessary, and
# leave `release_conn` constant throughout the function. That way, if
# the function recurses, the original value of `release_conn` will be
# passed down into the recursive call, and its value will be respected.
#
# See issue #651 [1] for details.
#
# [1] <https://github.com/urllib3/urllib3/issues/651>
release_this_conn = release_conn

http_tunnel_required = connection_requires_http_tunnel(
self.proxy, self.proxy_config, destination_scheme
)

# Merge the proxy headers. Only done when not using HTTP CONNECT. We
# have to copy the headers dict so we can safely change it without those
# changes being reflected in anyone else's copy.
if not http_tunnel_required:
headers = headers.copy() # type: ignore[attr-defined]
headers.update(self.proxy_headers) # type: ignore[union-attr]

# Must keep the exception bound to a separate variable or else Python 3
# complains about UnboundLocalError.
err = None

# Keep track of whether we cleanly exited the except block. This
# ensures we do proper cleanup in finally.
clean_exit = False

# Rewind body position, if needed. Record current position
# for future rewinds in the event of a redirect/retry.
body_pos = set_file_position(body, body_pos)

try:
# Request a connection from the queue.
timeout_obj = self._get_timeout(timeout)
conn = self._get_conn(timeout=pool_timeout)

conn.timeout = timeout_obj.connect_timeout # type: ignore[assignment]

# Is this a closed/new connection that requires CONNECT tunnelling?
if self.proxy is not None and http_tunnel_required and conn.is_closed:
try:
self._prepare_proxy(conn)
except (BaseSSLError, OSError, SocketTimeout) as e:
self._raise_timeout(
err=e, url=self.proxy.url, timeout_value=conn.timeout
)
raise

# If we're going to release the connection in ``finally:``, then
# the response doesn't need to know about the connection. Otherwise
# it will also try to release it and we'll have a double-release
# mess.
response_conn = conn if not release_conn else None

# Make the request on the HTTPConnection object
> response = self._make_request(
conn,
method,
url,
timeout=timeout_obj,
body=body,
headers=headers,
chunked=chunked,
retries=retries,
response_conn=response_conn,
preload_content=preload_content,
decode_content=decode_content,
**response_kw,
)

venv/lib/python3.11/site-packages/urllib3/connectionpool.py:789:
_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _
venv/lib/python3.11/site-packages/urllib3/connectionpool.py:490: in _make_request
raise new_e
venv/lib/python3.11/site-packages/urllib3/connectionpool.py:466: in _make_request
self._validate_conn(conn)
venv/lib/python3.11/site-packages/urllib3/connectionpool.py:1095: in _validate_conn
conn.connect()
venv/lib/python3.11/site-packages/urllib3/connection.py:615: in connect
self.sock = sock = self._new_conn()
_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _

self = <urllib3.connection.HTTPSConnection object at 0x10418d650>

def _new_conn(self) -> socket.socket:
"""Establish a socket connection and set nodelay settings on it.

:return: New socket connection.
"""
try:
sock = connection.create_connection(
(self._dns_host, self.port),
self.timeout,
source_address=self.source_address,
socket_options=self.socket_options,
)
except socket.gaierror as e:
> raise NameResolutionError(self.host, self, e) from e
E urllib3.exceptions.NameResolutionError: <urllib3.connection.HTTPSConnection object at 0x10418d650>: Failed to resolve 'addons.allizom.org' ([Errno 8] nodename nor servname provided, or not known)

venv/lib/python3.11/site-packages/urllib3/connection.py:203: NameResolutionError

The above exception was the direct cause of the following exception:

self = <requests.adapters.HTTPAdapter object at 0x10418e650>, request = <PreparedRequest [POST]>, stream = False, timeout = Timeout(connect=None, read=None, total=None), verify = True, cert = None
proxies = OrderedDict()

def send(
self, request, stream=False, timeout=None, verify=True, cert=None, proxies=None
):
"""Sends PreparedRequest object. Returns Response object.

:param request: The :class:`PreparedRequest <PreparedRequest>` being sent.
:param stream: (optional) Whether to stream the request content.
:param timeout: (optional) How long to wait for the server to send
data before giving up, as a float, or a :ref:`(connect timeout,
read timeout) <timeouts>` tuple.
:type timeout: float or tuple or urllib3 Timeout object
:param verify: (optional) Either a boolean, in which case it controls whether
we verify the server's TLS certificate, or a string, in which case it
must be a path to a CA bundle to use
:param cert: (optional) Any user-provided SSL certificate to be trusted.
:param proxies: (optional) The proxies dictionary to apply to the request.
:rtype: requests.Response
"""

try:
conn = self._get_connection(request, verify, proxies=proxies, cert=cert)
except LocationValueError as e:
raise InvalidURL(e, request=request)

self.cert_verify(conn, request.url, verify, cert)
url = self.request_url(request, proxies)
self.add_headers(
request,
stream=stream,
timeout=timeout,
verify=verify,
cert=cert,
proxies=proxies,
)

chunked = not (request.body is None or "Content-Length" in request.headers)

if isinstance(timeout, tuple):
try:
connect, read = timeout
timeout = TimeoutSauce(connect=connect, read=read)
except ValueError:
raise ValueError(
f"Invalid timeout {timeout}. Pass a (connect, read) timeout tuple, "
f"or a single float to set both timeouts to the same value."
)
elif isinstance(timeout, TimeoutSauce):
pass
else:
timeout = TimeoutSauce(connect=timeout, read=timeout)

try:
> resp = conn.urlopen(
method=request.method,
url=url,
body=request.body,
headers=request.headers,
redirect=False,
assert_same_host=False,
preload_content=False,
decode_content=False,
retries=self.max_retries,
timeout=timeout,
chunked=chunked,
)

venv/lib/python3.11/site-packages/requests/adapters.py:564:
_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _
venv/lib/python3.11/site-packages/urllib3/connectionpool.py:843: in urlopen
retries = retries.increment(
_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _

self = Retry(total=0, connect=None, read=False, redirect=None, status=None), method = 'POST', url = '/api/v5/addons/upload/', response = None
error = NameResolutionError("<urllib3.connection.HTTPSConnection object at 0x10418d650>: Failed to resolve 'addons.allizom.org' ([Errno 8] nodename nor servname provided, or not known)")
_pool = <urllib3.connectionpool.HTTPSConnectionPool object at 0x10418d2d0>, _stacktrace = <traceback object at 0x10418d440>

def increment(
self,
method: str | None = None,
url: str | None = None,
response: BaseHTTPResponse | None = None,
error: Exception | None = None,
_pool: ConnectionPool | None = None,
_stacktrace: TracebackType | None = None,
) -> Self:
"""Return a new Retry object with incremented retry counters.

:param response: A response object, or None, if the server did not
return a response.
:type response: :class:`~urllib3.response.BaseHTTPResponse`
:param Exception error: An error encountered during the request, or
None if the response was received successfully.

:return: A new ``Retry`` object.
"""
if self.total is False and error:
# Disabled, indicate to re-raise the error.
raise reraise(type(error), error, _stacktrace)

total = self.total
if total is not None:
total -= 1

connect = self.connect
read = self.read
redirect = self.redirect
status_count = self.status
other = self.other
cause = "unknown"
status = None
redirect_location = None

if error and self._is_connection_error(error):
# Connect retry?
if connect is False:
raise reraise(type(error), error, _stacktrace)
elif connect is not None:
connect -= 1

elif error and self._is_read_error(error):
# Read retry?
if read is False or method is None or not self._is_method_retryable(method):
raise reraise(type(error), error, _stacktrace)
elif read is not None:
read -= 1

elif error:
# Other retry?
if other is not None:
other -= 1

elif response and response.get_redirect_location():
# Redirect retry?
if redirect is not None:
redirect -= 1
cause = "too many redirects"
response_redirect_location = response.get_redirect_location()
if response_redirect_location:
redirect_location = response_redirect_location
status = response.status

else:
# Incrementing because of a server error like a 500 in
# status_forcelist and the given method is in the allowed_methods
cause = ResponseError.GENERIC_ERROR
if response and response.status:
if status_count is not None:
status_count -= 1
cause = ResponseError.SPECIFIC_ERROR.format(status_code=response.status)
status = response.status

history = self.history + (
RequestHistory(method, url, error, status, redirect_location),
)

new_retry = self.new(
total=total,
connect=connect,
read=read,
redirect=redirect,
status=status_count,
other=other,
history=history,
)

if new_retry.is_exhausted():
reason = error or ResponseError(cause)
> raise MaxRetryError(_pool, url, reason) from reason # type: ignore[arg-type]
E urllib3.exceptions.MaxRetryError: HTTPSConnectionPool(host='addons.allizom.org', port=443): Max retries exceeded with url: /api/v5/addons/upload/ (Caused by NameResolutionError("<urllib3.connection.HTTPSConnection object at 0x10418d650>: Failed to resolve 'addons.allizom.org' ([Errno 8] nodename nor servname provided, or not known)"))

venv/lib/python3.11/site-packages/urllib3/util/retry.py:519: MaxRetryError

During handling of the above exception, another exception occurred:

base_url = 'https://addons.allizom.org', session_auth = 'ldvd5ag27bkfpukx6rn2lcj0yuvakt3v', trademark_name = 'Firefox in addon name'

@pytest.mark.parametrize(
"trademark_name",
[
"Firefox in addon name",
"Mozilla in addon name",
],
)
@pytest.mark.serial
@pytest.mark.create_session("api_user")
def test_submit_xpi_with_trademark_restricted_user(
base_url, session_auth, trademark_name
):
"""Upload an addon that includes the 'Firefox' or 'Mozilla' names;
regular users are not allowed to submit such addons"""
# create a minimal manifest with a trademark name
manifest = {**payloads.minimal_manifest, "name": trademark_name}
api_helpers.make_addon(manifest)
with open("sample-addons/make-addon.zip", "rb") as file:
> upload = requests.post(
url=f"{base_url}{_upload}",
headers={"Authorization": f"Session {session_auth}"},
files={"upload": file},
data={"channel": "listed"},
)

tests/api_w/test_addon_uploads.py:336:
_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _
venv/lib/python3.11/site-packages/requests/api.py:115: in post
return request("post", url, data=data, json=json, **kwargs)
venv/lib/python3.11/site-packages/requests/api.py:59: in request
return session.request(method=method, url=url, **kwargs)
venv/lib/python3.11/site-packages/requests/sessions.py:589: in request
resp = self.send(prep, **send_kwargs)
venv/lib/python3.11/site-packages/requests/sessions.py:703: in send
r = adapter.send(request, **kwargs)
_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _

self = <requests.adapters.HTTPAdapter object at 0x10418e650>, request = <PreparedRequest [POST]>, stream = False, timeout = Timeout(connect=None, read=None, total=None), verify = True, cert = None
proxies = OrderedDict()

def send(
self, request, stream=False, timeout=None, verify=True, cert=None, proxies=None
):
"""Sends PreparedRequest object. Returns Response object.

:param request: The :class:`PreparedRequest <PreparedRequest>` being sent.
:param stream: (optional) Whether to stream the request content.
:param timeout: (optional) How long to wait for the server to send
data before giving up, as a float, or a :ref:`(connect timeout,
read timeout) <timeouts>` tuple.
:type timeout: float or tuple or urllib3 Timeout object
:param verify: (optional) Either a boolean, in which case it controls whether
we verify the server's TLS certificate, or a string, in which case it
must be a path to a CA bundle to use
:param cert: (optional) Any user-provided SSL certificate to be trusted.
:param proxies: (optional) The proxies dictionary to apply to the request.
:rtype: requests.Response
"""

try:
conn = self._get_connection(request, verify, proxies=proxies, cert=cert)
except LocationValueError as e:
raise InvalidURL(e, request=request)

self.cert_verify(conn, request.url, verify, cert)
url = self.request_url(request, proxies)
self.add_headers(
request,
stream=stream,
timeout=timeout,
verify=verify,
cert=cert,
proxies=proxies,
)

chunked = not (request.body is None or "Content-Length" in request.headers)

if isinstance(timeout, tuple):
try:
connect, read = timeout
timeout = TimeoutSauce(connect=connect, read=read)
except ValueError:
raise ValueError(
f"Invalid timeout {timeout}. Pass a (connect, read) timeout tuple, "
f"or a single float to set both timeouts to the same value."
)
elif isinstance(timeout, TimeoutSauce):
pass
else:
timeout = TimeoutSauce(connect=timeout, read=timeout)

try:
resp = conn.urlopen(
method=request.method,
url=url,
body=request.body,
headers=request.headers,
redirect=False,
assert_same_host=False,
preload_content=False,
decode_content=False,
retries=self.max_retries,
timeout=timeout,
chunked=chunked,
)

except (ProtocolError, OSError) as err:
raise ConnectionError(err, request=request)

except MaxRetryError as e:
if isinstance(e.reason, ConnectTimeoutError):
# TODO: Remove this in 3.0.0: see #2811
if not isinstance(e.reason, NewConnectionError):
raise ConnectTimeout(e, request=request)

if isinstance(e.reason, ResponseError):
raise RetryError(e, request=request)

if isinstance(e.reason, _ProxyError):
raise ProxyError(e, request=request)

if isinstance(e.reason, _SSLError):
# This branch is for urllib3 v1.22 and later.
raise SSLError(e, request=request)

> raise ConnectionError(e, request=request)
E requests.exceptions.ConnectionError: HTTPSConnectionPool(host='addons.allizom.org', port=443): Max retries exceeded with url: /api/v5/addons/upload/ (Caused by NameResolutionError("<urllib3.connection.HTTPSConnection object at 0x10418d650>: Failed to resolve 'addons.allizom.org' ([Errno 8] nodename nor servname provided, or not known)"))

venv/lib/python3.11/site-packages/requests/adapters.py:597: ConnectionError
------------------------------Captured stdout call------------------------------
Manifest content: {'manifest_version': 2, 'version': '1.0', 'name': 'Firefox in addon name'}
Failed tests/api_w/test_addon_uploads.py::test_submit_xpi_with_trademark_restricted_user[Mozilla in addon name] 0.01
self = <urllib3.connection.HTTPSConnection object at 0x103f9e850>

def _new_conn(self) -> socket.socket:
"""Establish a socket connection and set nodelay settings on it.

:return: New socket connection.
"""
try:
> sock = connection.create_connection(
(self._dns_host, self.port),
self.timeout,
source_address=self.source_address,
socket_options=self.socket_options,
)

venv/lib/python3.11/site-packages/urllib3/connection.py:196:
_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _
venv/lib/python3.11/site-packages/urllib3/util/connection.py:60: in create_connection
for res in socket.getaddrinfo(host, port, family, socket.SOCK_STREAM):
_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _

host = 'addons.allizom.org', port = 443, family = <AddressFamily.AF_UNSPEC: 0>, type = <SocketKind.SOCK_STREAM: 1>, proto = 0, flags = 0

def getaddrinfo(host, port, family=0, type=0, proto=0, flags=0):
"""Resolve host and port into list of address info entries.

Translate the host/port argument into a sequence of 5-tuples that contain
all the necessary arguments for creating a socket connected to that service.
host is a domain name, a string representation of an IPv4/v6 address or
None. port is a string service name such as 'http', a numeric port number or
None. By passing None as the value of host and port, you can pass NULL to
the underlying C API.

The family, type and proto arguments can be optionally specified in order to
narrow the list of addresses returned. Passing zero as a value for each of
these arguments selects the full range of results.
"""
# We override this function since we want to translate the numeric family
# and socket type values to enum constants.
addrlist = []
> for res in _socket.getaddrinfo(host, port, family, type, proto, flags):
E socket.gaierror: [Errno 8] nodename nor servname provided, or not known

/Library/Frameworks/Python.framework/Versions/3.11/lib/python3.11/socket.py:962: gaierror

The above exception was the direct cause of the following exception:

self = <urllib3.connectionpool.HTTPSConnectionPool object at 0x103f9fb10>, method = 'POST', url = '/api/v5/addons/upload/'
body = b'--fcd5be72ac7f21fcf9d1d9f12e234129\r\nContent-Disposition: form-data; name="channel"\r\n\r\nlisted\r\n--fcd5be72ac7f...\x05\x06\x00\x00\x00\x00\x01\x00\x01\x00;\x00\x00\x00u\x00\x00\x00\x00\x00\r\n--fcd5be72ac7f21fcf9d1d9f12e234129--\r\n'
headers = {'User-Agent': 'python-requests/2.32.0', 'Accept-Encoding': 'gzip, deflate', 'Accept': '*/*', 'Connection': 'keep-aliv...j0yuvakt3v', 'Content-Length': '444', 'Content-Type': 'multipart/form-data; boundary=fcd5be72ac7f21fcf9d1d9f12e234129'}
retries = Retry(total=0, connect=None, read=False, redirect=None, status=None), redirect = False, assert_same_host = False, timeout = Timeout(connect=None, read=None, total=None), pool_timeout = None
release_conn = False, chunked = False, body_pos = None, preload_content = False, decode_content = False, response_kw = {}
parsed_url = Url(scheme=None, auth=None, host=None, port=None, path='/api/v5/addons/upload/', query=None, fragment=None), destination_scheme = None, conn = None, release_this_conn = True
http_tunnel_required = False, err = None, clean_exit = False

def urlopen( # type: ignore[override]
self,
method: str,
url: str,
body: _TYPE_BODY | None = None,
headers: typing.Mapping[str, str] | None = None,
retries: Retry | bool | int | None = None,
redirect: bool = True,
assert_same_host: bool = True,
timeout: _TYPE_TIMEOUT = _DEFAULT_TIMEOUT,
pool_timeout: int | None = None,
release_conn: bool | None = None,
chunked: bool = False,
body_pos: _TYPE_BODY_POSITION | None = None,
preload_content: bool = True,
decode_content: bool = True,
**response_kw: typing.Any,
) -> BaseHTTPResponse:
"""
Get a connection from the pool and perform an HTTP request. This is the
lowest level call for making a request, so you'll need to specify all
the raw details.

.. note::

More commonly, it's appropriate to use a convenience method
such as :meth:`request`.

.. note::

`release_conn` will only behave as expected if
`preload_content=False` because we want to make
`preload_content=False` the default behaviour someday soon without
breaking backwards compatibility.

:param method:
HTTP request method (such as GET, POST, PUT, etc.)

:param url:
The URL to perform the request on.

:param body:
Data to send in the request body, either :class:`str`, :class:`bytes`,
an iterable of :class:`str`/:class:`bytes`, or a file-like object.

:param headers:
Dictionary of custom headers to send, such as User-Agent,
If-None-Match, etc. If None, pool headers are used. If provided,
these headers completely replace any pool-specific headers.

:param retries:
Configure the number of retries to allow before raising a
:class:`~urllib3.exceptions.MaxRetryError` exception.

If ``None`` (default) will retry 3 times, see ``Retry.DEFAULT``. Pass a
:class:`~urllib3.util.retry.Retry` object for fine-grained control
over different types of retries.
Pass an integer number to retry connection errors that many times,
but no other types of errors. Pass zero to never retry.

If ``False``, then retries are disabled and any exception is raised
immediately. Also, instead of raising a MaxRetryError on redirects,
the redirect response will be returned.

:type retries: :class:`~urllib3.util.retry.Retry`, False, or an int.

:param redirect:
If True, automatically handle redirects (status codes 301, 302,
303, 307, 308). Each redirect counts as a retry. Disabling retries
will disable redirect, too.

:param assert_same_host:
If ``True``, will make sure that the host of the pool requests is
consistent else will raise HostChangedError. When ``False``, you can
use the pool on an HTTP proxy and request foreign hosts.

:param timeout:
If specified, overrides the default timeout for this one
request. It may be a float (in seconds) or an instance of
:class:`urllib3.util.Timeout`.

:param pool_timeout:
If set and the pool is set to block=True, then this method will
block for ``pool_timeout`` seconds and raise EmptyPoolError if no
connection is available within the time period.

:param bool preload_content:
If True, the response's body will be preloaded into memory.

:param bool decode_content:
If True, will attempt to decode the body based on the
'content-encoding' header.

:param release_conn:
If False, then the urlopen call will not release the connection
back into the pool once a response is received (but will release if
you read the entire contents of the response such as when
`preload_content=True`). This is useful if you're not preloading
the response's content immediately. You will need to call
``r.release_conn()`` on the response ``r`` to return the connection
back into the pool. If None, it takes the value of ``preload_content``
which defaults to ``True``.

:param bool chunked:
If True, urllib3 will send the body using chunked transfer
encoding. Otherwise, urllib3 will send the body using the standard
content-length form. Defaults to False.

:param int body_pos:
Position to seek to in file-like body in the event of a retry or
redirect. Typically this won't need to be set because urllib3 will
auto-populate the value when needed.
"""
parsed_url = parse_url(url)
destination_scheme = parsed_url.scheme

if headers is None:
headers = self.headers

if not isinstance(retries, Retry):
retries = Retry.from_int(retries, redirect=redirect, default=self.retries)

if release_conn is None:
release_conn = preload_content

# Check host
if assert_same_host and not self.is_same_host(url):
raise HostChangedError(self, url, retries)

# Ensure that the URL we're connecting to is properly encoded
if url.startswith("/"):
url = to_str(_encode_target(url))
else:
url = to_str(parsed_url.url)

conn = None

# Track whether `conn` needs to be released before
# returning/raising/recursing. Update this variable if necessary, and
# leave `release_conn` constant throughout the function. That way, if
# the function recurses, the original value of `release_conn` will be
# passed down into the recursive call, and its value will be respected.
#
# See issue #651 [1] for details.
#
# [1] <https://github.com/urllib3/urllib3/issues/651>
release_this_conn = release_conn

http_tunnel_required = connection_requires_http_tunnel(
self.proxy, self.proxy_config, destination_scheme
)

# Merge the proxy headers. Only done when not using HTTP CONNECT. We
# have to copy the headers dict so we can safely change it without those
# changes being reflected in anyone else's copy.
if not http_tunnel_required:
headers = headers.copy() # type: ignore[attr-defined]
headers.update(self.proxy_headers) # type: ignore[union-attr]

# Must keep the exception bound to a separate variable or else Python 3
# complains about UnboundLocalError.
err = None

# Keep track of whether we cleanly exited the except block. This
# ensures we do proper cleanup in finally.
clean_exit = False

# Rewind body position, if needed. Record current position
# for future rewinds in the event of a redirect/retry.
body_pos = set_file_position(body, body_pos)

try:
# Request a connection from the queue.
timeout_obj = self._get_timeout(timeout)
conn = self._get_conn(timeout=pool_timeout)

conn.timeout = timeout_obj.connect_timeout # type: ignore[assignment]

# Is this a closed/new connection that requires CONNECT tunnelling?
if self.proxy is not None and http_tunnel_required and conn.is_closed:
try:
self._prepare_proxy(conn)
except (BaseSSLError, OSError, SocketTimeout) as e:
self._raise_timeout(
err=e, url=self.proxy.url, timeout_value=conn.timeout
)
raise

# If we're going to release the connection in ``finally:``, then
# the response doesn't need to know about the connection. Otherwise
# it will also try to release it and we'll have a double-release
# mess.
response_conn = conn if not release_conn else None

# Make the request on the HTTPConnection object
> response = self._make_request(
conn,
method,
url,
timeout=timeout_obj,
body=body,
headers=headers,
chunked=chunked,
retries=retries,
response_conn=response_conn,
preload_content=preload_content,
decode_content=decode_content,
**response_kw,
)

venv/lib/python3.11/site-packages/urllib3/connectionpool.py:789:
_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _
venv/lib/python3.11/site-packages/urllib3/connectionpool.py:490: in _make_request
raise new_e
venv/lib/python3.11/site-packages/urllib3/connectionpool.py:466: in _make_request
self._validate_conn(conn)
venv/lib/python3.11/site-packages/urllib3/connectionpool.py:1095: in _validate_conn
conn.connect()
venv/lib/python3.11/site-packages/urllib3/connection.py:615: in connect
self.sock = sock = self._new_conn()
_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _

self = <urllib3.connection.HTTPSConnection object at 0x103f9e850>

def _new_conn(self) -> socket.socket:
"""Establish a socket connection and set nodelay settings on it.

:return: New socket connection.
"""
try:
sock = connection.create_connection(
(self._dns_host, self.port),
self.timeout,
source_address=self.source_address,
socket_options=self.socket_options,
)
except socket.gaierror as e:
> raise NameResolutionError(self.host, self, e) from e
E urllib3.exceptions.NameResolutionError: <urllib3.connection.HTTPSConnection object at 0x103f9e850>: Failed to resolve 'addons.allizom.org' ([Errno 8] nodename nor servname provided, or not known)

venv/lib/python3.11/site-packages/urllib3/connection.py:203: NameResolutionError

The above exception was the direct cause of the following exception:

self = <requests.adapters.HTTPAdapter object at 0x103f9e990>, request = <PreparedRequest [POST]>, stream = False, timeout = Timeout(connect=None, read=None, total=None), verify = True, cert = None
proxies = OrderedDict()

def send(
self, request, stream=False, timeout=None, verify=True, cert=None, proxies=None
):
"""Sends PreparedRequest object. Returns Response object.

:param request: The :class:`PreparedRequest <PreparedRequest>` being sent.
:param stream: (optional) Whether to stream the request content.
:param timeout: (optional) How long to wait for the server to send
data before giving up, as a float, or a :ref:`(connect timeout,
read timeout) <timeouts>` tuple.
:type timeout: float or tuple or urllib3 Timeout object
:param verify: (optional) Either a boolean, in which case it controls whether
we verify the server's TLS certificate, or a string, in which case it
must be a path to a CA bundle to use
:param cert: (optional) Any user-provided SSL certificate to be trusted.
:param proxies: (optional) The proxies dictionary to apply to the request.
:rtype: requests.Response
"""

try:
conn = self._get_connection(request, verify, proxies=proxies, cert=cert)
except LocationValueError as e:
raise InvalidURL(e, request=request)

self.cert_verify(conn, request.url, verify, cert)
url = self.request_url(request, proxies)
self.add_headers(
request,
stream=stream,
timeout=timeout,
verify=verify,
cert=cert,
proxies=proxies,
)

chunked = not (request.body is None or "Content-Length" in request.headers)

if isinstance(timeout, tuple):
try:
connect, read = timeout
timeout = TimeoutSauce(connect=connect, read=read)
except ValueError:
raise ValueError(
f"Invalid timeout {timeout}. Pass a (connect, read) timeout tuple, "
f"or a single float to set both timeouts to the same value."
)
elif isinstance(timeout, TimeoutSauce):
pass
else:
timeout = TimeoutSauce(connect=timeout, read=timeout)

try:
> resp = conn.urlopen(
method=request.method,
url=url,
body=request.body,
headers=request.headers,
redirect=False,
assert_same_host=False,
preload_content=False,
decode_content=False,
retries=self.max_retries,
timeout=timeout,
chunked=chunked,
)

venv/lib/python3.11/site-packages/requests/adapters.py:564:
_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _
venv/lib/python3.11/site-packages/urllib3/connectionpool.py:843: in urlopen
retries = retries.increment(
_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _

self = Retry(total=0, connect=None, read=False, redirect=None, status=None), method = 'POST', url = '/api/v5/addons/upload/', response = None
error = NameResolutionError("<urllib3.connection.HTTPSConnection object at 0x103f9e850>: Failed to resolve 'addons.allizom.org' ([Errno 8] nodename nor servname provided, or not known)")
_pool = <urllib3.connectionpool.HTTPSConnectionPool object at 0x103f9fb10>, _stacktrace = <traceback object at 0x103f9e800>

def increment(
self,
method: str | None = None,
url: str | None = None,
response: BaseHTTPResponse | None = None,
error: Exception | None = None,
_pool: ConnectionPool | None = None,
_stacktrace: TracebackType | None = None,
) -> Self:
"""Return a new Retry object with incremented retry counters.

:param response: A response object, or None, if the server did not
return a response.
:type response: :class:`~urllib3.response.BaseHTTPResponse`
:param Exception error: An error encountered during the request, or
None if the response was received successfully.

:return: A new ``Retry`` object.
"""
if self.total is False and error:
# Disabled, indicate to re-raise the error.
raise reraise(type(error), error, _stacktrace)

total = self.total
if total is not None:
total -= 1

connect = self.connect
read = self.read
redirect = self.redirect
status_count = self.status
other = self.other
cause = "unknown"
status = None
redirect_location = None

if error and self._is_connection_error(error):
# Connect retry?
if connect is False:
raise reraise(type(error), error, _stacktrace)
elif connect is not None:
connect -= 1

elif error and self._is_read_error(error):
# Read retry?
if read is False or method is None or not self._is_method_retryable(method):
raise reraise(type(error), error, _stacktrace)
elif read is not None:
read -= 1

elif error:
# Other retry?
if other is not None:
other -= 1

elif response and response.get_redirect_location():
# Redirect retry?
if redirect is not None:
redirect -= 1
cause = "too many redirects"
response_redirect_location = response.get_redirect_location()
if response_redirect_location:
redirect_location = response_redirect_location
status = response.status

else:
# Incrementing because of a server error like a 500 in
# status_forcelist and the given method is in the allowed_methods
cause = ResponseError.GENERIC_ERROR
if response and response.status:
if status_count is not None:
status_count -= 1
cause = ResponseError.SPECIFIC_ERROR.format(status_code=response.status)
status = response.status

history = self.history + (
RequestHistory(method, url, error, status, redirect_location),
)

new_retry = self.new(
total=total,
connect=connect,
read=read,
redirect=redirect,
status=status_count,
other=other,
history=history,
)

if new_retry.is_exhausted():
reason = error or ResponseError(cause)
> raise MaxRetryError(_pool, url, reason) from reason # type: ignore[arg-type]
E urllib3.exceptions.MaxRetryError: HTTPSConnectionPool(host='addons.allizom.org', port=443): Max retries exceeded with url: /api/v5/addons/upload/ (Caused by NameResolutionError("<urllib3.connection.HTTPSConnection object at 0x103f9e850>: Failed to resolve 'addons.allizom.org' ([Errno 8] nodename nor servname provided, or not known)"))

venv/lib/python3.11/site-packages/urllib3/util/retry.py:519: MaxRetryError

During handling of the above exception, another exception occurred:

base_url = 'https://addons.allizom.org', session_auth = 'ldvd5ag27bkfpukx6rn2lcj0yuvakt3v', trademark_name = 'Mozilla in addon name'

@pytest.mark.parametrize(
"trademark_name",
[
"Firefox in addon name",
"Mozilla in addon name",
],
)
@pytest.mark.serial
@pytest.mark.create_session("api_user")
def test_submit_xpi_with_trademark_restricted_user(
base_url, session_auth, trademark_name
):
"""Upload an addon that includes the 'Firefox' or 'Mozilla' names;
regular users are not allowed to submit such addons"""
# create a minimal manifest with a trademark name
manifest = {**payloads.minimal_manifest, "name": trademark_name}
api_helpers.make_addon(manifest)
with open("sample-addons/make-addon.zip", "rb") as file:
> upload = requests.post(
url=f"{base_url}{_upload}",
headers={"Authorization": f"Session {session_auth}"},
files={"upload": file},
data={"channel": "listed"},
)

tests/api_w/test_addon_uploads.py:336:
_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _
venv/lib/python3.11/site-packages/requests/api.py:115: in post
return request("post", url, data=data, json=json, **kwargs)
venv/lib/python3.11/site-packages/requests/api.py:59: in request
return session.request(method=method, url=url, **kwargs)
venv/lib/python3.11/site-packages/requests/sessions.py:589: in request
resp = self.send(prep, **send_kwargs)
venv/lib/python3.11/site-packages/requests/sessions.py:703: in send
r = adapter.send(request, **kwargs)
_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _

self = <requests.adapters.HTTPAdapter object at 0x103f9e990>, request = <PreparedRequest [POST]>, stream = False, timeout = Timeout(connect=None, read=None, total=None), verify = True, cert = None
proxies = OrderedDict()

def send(
self, request, stream=False, timeout=None, verify=True, cert=None, proxies=None
):
"""Sends PreparedRequest object. Returns Response object.

:param request: The :class:`PreparedRequest <PreparedRequest>` being sent.
:param stream: (optional) Whether to stream the request content.
:param timeout: (optional) How long to wait for the server to send
data before giving up, as a float, or a :ref:`(connect timeout,
read timeout) <timeouts>` tuple.
:type timeout: float or tuple or urllib3 Timeout object
:param verify: (optional) Either a boolean, in which case it controls whether
we verify the server's TLS certificate, or a string, in which case it
must be a path to a CA bundle to use
:param cert: (optional) Any user-provided SSL certificate to be trusted.
:param proxies: (optional) The proxies dictionary to apply to the request.
:rtype: requests.Response
"""

try:
conn = self._get_connection(request, verify, proxies=proxies, cert=cert)
except LocationValueError as e:
raise InvalidURL(e, request=request)

self.cert_verify(conn, request.url, verify, cert)
url = self.request_url(request, proxies)
self.add_headers(
request,
stream=stream,
timeout=timeout,
verify=verify,
cert=cert,
proxies=proxies,
)

chunked = not (request.body is None or "Content-Length" in request.headers)

if isinstance(timeout, tuple):
try:
connect, read = timeout
timeout = TimeoutSauce(connect=connect, read=read)
except ValueError:
raise ValueError(
f"Invalid timeout {timeout}. Pass a (connect, read) timeout tuple, "
f"or a single float to set both timeouts to the same value."
)
elif isinstance(timeout, TimeoutSauce):
pass
else:
timeout = TimeoutSauce(connect=timeout, read=timeout)

try:
resp = conn.urlopen(
method=request.method,
url=url,
body=request.body,
headers=request.headers,
redirect=False,
assert_same_host=False,
preload_content=False,
decode_content=False,
retries=self.max_retries,
timeout=timeout,
chunked=chunked,
)

except (ProtocolError, OSError) as err:
raise ConnectionError(err, request=request)

except MaxRetryError as e:
if isinstance(e.reason, ConnectTimeoutError):
# TODO: Remove this in 3.0.0: see #2811
if not isinstance(e.reason, NewConnectionError):
raise ConnectTimeout(e, request=request)

if isinstance(e.reason, ResponseError):
raise RetryError(e, request=request)

if isinstance(e.reason, _ProxyError):
raise ProxyError(e, request=request)

if isinstance(e.reason, _SSLError):
# This branch is for urllib3 v1.22 and later.
raise SSLError(e, request=request)

> raise ConnectionError(e, request=request)
E requests.exceptions.ConnectionError: HTTPSConnectionPool(host='addons.allizom.org', port=443): Max retries exceeded with url: /api/v5/addons/upload/ (Caused by NameResolutionError("<urllib3.connection.HTTPSConnection object at 0x103f9e850>: Failed to resolve 'addons.allizom.org' ([Errno 8] nodename nor servname provided, or not known)"))

venv/lib/python3.11/site-packages/requests/adapters.py:597: ConnectionError
------------------------------Captured stdout call------------------------------
Manifest content: {'manifest_version': 2, 'version': '1.0', 'name': 'Mozilla in addon name'}
Failed tests/api_w/test_addon_uploads.py::test_submit_addon_with_reserved_guid[reserved_guid@mozilla.com] 0.01
self = <urllib3.connection.HTTPSConnection object at 0x103bc2850>

def _new_conn(self) -> socket.socket:
"""Establish a socket connection and set nodelay settings on it.

:return: New socket connection.
"""
try:
> sock = connection.create_connection(
(self._dns_host, self.port),
self.timeout,
source_address=self.source_address,
socket_options=self.socket_options,
)

venv/lib/python3.11/site-packages/urllib3/connection.py:196:
_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _
venv/lib/python3.11/site-packages/urllib3/util/connection.py:60: in create_connection
for res in socket.getaddrinfo(host, port, family, socket.SOCK_STREAM):
_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _

host = 'addons.allizom.org', port = 443, family = <AddressFamily.AF_UNSPEC: 0>, type = <SocketKind.SOCK_STREAM: 1>, proto = 0, flags = 0

def getaddrinfo(host, port, family=0, type=0, proto=0, flags=0):
"""Resolve host and port into list of address info entries.

Translate the host/port argument into a sequence of 5-tuples that contain
all the necessary arguments for creating a socket connected to that service.
host is a domain name, a string representation of an IPv4/v6 address or
None. port is a string service name such as 'http', a numeric port number or
None. By passing None as the value of host and port, you can pass NULL to
the underlying C API.

The family, type and proto arguments can be optionally specified in order to
narrow the list of addresses returned. Passing zero as a value for each of
these arguments selects the full range of results.
"""
# We override this function since we want to translate the numeric family
# and socket type values to enum constants.
addrlist = []
> for res in _socket.getaddrinfo(host, port, family, type, proto, flags):
E socket.gaierror: [Errno 8] nodename nor servname provided, or not known

/Library/Frameworks/Python.framework/Versions/3.11/lib/python3.11/socket.py:962: gaierror

The above exception was the direct cause of the following exception:

self = <urllib3.connectionpool.HTTPSConnectionPool object at 0x103bc2b10>, method = 'POST', url = '/api/v5/addons/upload/'
body = b'--8a872a142bdadc2b9eb381c99d2da510\r\nContent-Disposition: form-data; name="channel"\r\n\r\nlisted\r\n--8a872a142bda...5\x06\x00\x00\x00\x00\x01\x00\x01\x00;\x00\x00\x00\xba\x00\x00\x00\x00\x00\r\n--8a872a142bdadc2b9eb381c99d2da510--\r\n'
headers = {'User-Agent': 'python-requests/2.32.0', 'Accept-Encoding': 'gzip, deflate', 'Accept': '*/*', 'Connection': 'keep-aliv...j0yuvakt3v', 'Content-Length': '513', 'Content-Type': 'multipart/form-data; boundary=8a872a142bdadc2b9eb381c99d2da510'}
retries = Retry(total=0, connect=None, read=False, redirect=None, status=None), redirect = False, assert_same_host = False, timeout = Timeout(connect=None, read=None, total=None), pool_timeout = None
release_conn = False, chunked = False, body_pos = None, preload_content = False, decode_content = False, response_kw = {}
parsed_url = Url(scheme=None, auth=None, host=None, port=None, path='/api/v5/addons/upload/', query=None, fragment=None), destination_scheme = None, conn = None, release_this_conn = True
http_tunnel_required = False, err = None, clean_exit = False

def urlopen( # type: ignore[override]
self,
method: str,
url: str,
body: _TYPE_BODY | None = None,
headers: typing.Mapping[str, str] | None = None,
retries: Retry | bool | int | None = None,
redirect: bool = True,
assert_same_host: bool = True,
timeout: _TYPE_TIMEOUT = _DEFAULT_TIMEOUT,
pool_timeout: int | None = None,
release_conn: bool | None = None,
chunked: bool = False,
body_pos: _TYPE_BODY_POSITION | None = None,
preload_content: bool = True,
decode_content: bool = True,
**response_kw: typing.Any,
) -> BaseHTTPResponse:
"""
Get a connection from the pool and perform an HTTP request. This is the
lowest level call for making a request, so you'll need to specify all
the raw details.

.. note::

More commonly, it's appropriate to use a convenience method
such as :meth:`request`.

.. note::

`release_conn` will only behave as expected if
`preload_content=False` because we want to make
`preload_content=False` the default behaviour someday soon without
breaking backwards compatibility.

:param method:
HTTP request method (such as GET, POST, PUT, etc.)

:param url:
The URL to perform the request on.

:param body:
Data to send in the request body, either :class:`str`, :class:`bytes`,
an iterable of :class:`str`/:class:`bytes`, or a file-like object.

:param headers:
Dictionary of custom headers to send, such as User-Agent,
If-None-Match, etc. If None, pool headers are used. If provided,
these headers completely replace any pool-specific headers.

:param retries:
Configure the number of retries to allow before raising a
:class:`~urllib3.exceptions.MaxRetryError` exception.

If ``None`` (default) will retry 3 times, see ``Retry.DEFAULT``. Pass a
:class:`~urllib3.util.retry.Retry` object for fine-grained control
over different types of retries.
Pass an integer number to retry connection errors that many times,
but no other types of errors. Pass zero to never retry.

If ``False``, then retries are disabled and any exception is raised
immediately. Also, instead of raising a MaxRetryError on redirects,
the redirect response will be returned.

:type retries: :class:`~urllib3.util.retry.Retry`, False, or an int.

:param redirect:
If True, automatically handle redirects (status codes 301, 302,
303, 307, 308). Each redirect counts as a retry. Disabling retries
will disable redirect, too.

:param assert_same_host:
If ``True``, will make sure that the host of the pool requests is
consistent else will raise HostChangedError. When ``False``, you can
use the pool on an HTTP proxy and request foreign hosts.

:param timeout:
If specified, overrides the default timeout for this one
request. It may be a float (in seconds) or an instance of
:class:`urllib3.util.Timeout`.

:param pool_timeout:
If set and the pool is set to block=True, then this method will
block for ``pool_timeout`` seconds and raise EmptyPoolError if no
connection is available within the time period.

:param bool preload_content:
If True, the response's body will be preloaded into memory.

:param bool decode_content:
If True, will attempt to decode the body based on the
'content-encoding' header.

:param release_conn:
If False, then the urlopen call will not release the connection
back into the pool once a response is received (but will release if
you read the entire contents of the response such as when
`preload_content=True`). This is useful if you're not preloading
the response's content immediately. You will need to call
``r.release_conn()`` on the response ``r`` to return the connection
back into the pool. If None, it takes the value of ``preload_content``
which defaults to ``True``.

:param bool chunked:
If True, urllib3 will send the body using chunked transfer
encoding. Otherwise, urllib3 will send the body using the standard
content-length form. Defaults to False.

:param int body_pos:
Position to seek to in file-like body in the event of a retry or
redirect. Typically this won't need to be set because urllib3 will
auto-populate the value when needed.
"""
parsed_url = parse_url(url)
destination_scheme = parsed_url.scheme

if headers is None:
headers = self.headers

if not isinstance(retries, Retry):
retries = Retry.from_int(retries, redirect=redirect, default=self.retries)

if release_conn is None:
release_conn = preload_content

# Check host
if assert_same_host and not self.is_same_host(url):
raise HostChangedError(self, url, retries)

# Ensure that the URL we're connecting to is properly encoded
if url.startswith("/"):
url = to_str(_encode_target(url))
else:
url = to_str(parsed_url.url)

conn = None

# Track whether `conn` needs to be released before
# returning/raising/recursing. Update this variable if necessary, and
# leave `release_conn` constant throughout the function. That way, if
# the function recurses, the original value of `release_conn` will be
# passed down into the recursive call, and its value will be respected.
#
# See issue #651 [1] for details.
#
# [1] <https://github.com/urllib3/urllib3/issues/651>
release_this_conn = release_conn

http_tunnel_required = connection_requires_http_tunnel(
self.proxy, self.proxy_config, destination_scheme
)

# Merge the proxy headers. Only done when not using HTTP CONNECT. We
# have to copy the headers dict so we can safely change it without those
# changes being reflected in anyone else's copy.
if not http_tunnel_required:
headers = headers.copy() # type: ignore[attr-defined]
headers.update(self.proxy_headers) # type: ignore[union-attr]

# Must keep the exception bound to a separate variable or else Python 3
# complains about UnboundLocalError.
err = None

# Keep track of whether we cleanly exited the except block. This
# ensures we do proper cleanup in finally.
clean_exit = False

# Rewind body position, if needed. Record current position
# for future rewinds in the event of a redirect/retry.
body_pos = set_file_position(body, body_pos)

try:
# Request a connection from the queue.
timeout_obj = self._get_timeout(timeout)
conn = self._get_conn(timeout=pool_timeout)

conn.timeout = timeout_obj.connect_timeout # type: ignore[assignment]

# Is this a closed/new connection that requires CONNECT tunnelling?
if self.proxy is not None and http_tunnel_required and conn.is_closed:
try:
self._prepare_proxy(conn)
except (BaseSSLError, OSError, SocketTimeout) as e:
self._raise_timeout(
err=e, url=self.proxy.url, timeout_value=conn.timeout
)
raise

# If we're going to release the connection in ``finally:``, then
# the response doesn't need to know about the connection. Otherwise
# it will also try to release it and we'll have a double-release
# mess.
response_conn = conn if not release_conn else None

# Make the request on the HTTPConnection object
> response = self._make_request(
conn,
method,
url,
timeout=timeout_obj,
body=body,
headers=headers,
chunked=chunked,
retries=retries,
response_conn=response_conn,
preload_content=preload_content,
decode_content=decode_content,
**response_kw,
)

venv/lib/python3.11/site-packages/urllib3/connectionpool.py:789:
_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _
venv/lib/python3.11/site-packages/urllib3/connectionpool.py:490: in _make_request
raise new_e
venv/lib/python3.11/site-packages/urllib3/connectionpool.py:466: in _make_request
self._validate_conn(conn)
venv/lib/python3.11/site-packages/urllib3/connectionpool.py:1095: in _validate_conn
conn.connect()
venv/lib/python3.11/site-packages/urllib3/connection.py:615: in connect
self.sock = sock = self._new_conn()
_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _

self = <urllib3.connection.HTTPSConnection object at 0x103bc2850>

def _new_conn(self) -> socket.socket:
"""Establish a socket connection and set nodelay settings on it.

:return: New socket connection.
"""
try:
sock = connection.create_connection(
(self._dns_host, self.port),
self.timeout,
source_address=self.source_address,
socket_options=self.socket_options,
)
except socket.gaierror as e:
> raise NameResolutionError(self.host, self, e) from e
E urllib3.exceptions.NameResolutionError: <urllib3.connection.HTTPSConnection object at 0x103bc2850>: Failed to resolve 'addons.allizom.org' ([Errno 8] nodename nor servname provided, or not known)

venv/lib/python3.11/site-packages/urllib3/connection.py:203: NameResolutionError

The above exception was the direct cause of the following exception:

self = <requests.adapters.HTTPAdapter object at 0x103bc2bd0>, request = <PreparedRequest [POST]>, stream = False, timeout = Timeout(connect=None, read=None, total=None), verify = True, cert = None
proxies = OrderedDict()

def send(
self, request, stream=False, timeout=None, verify=True, cert=None, proxies=None
):
"""Sends PreparedRequest object. Returns Response object.

:param request: The :class:`PreparedRequest <PreparedRequest>` being sent.
:param stream: (optional) Whether to stream the request content.
:param timeout: (optional) How long to wait for the server to send
data before giving up, as a float, or a :ref:`(connect timeout,
read timeout) <timeouts>` tuple.
:type timeout: float or tuple or urllib3 Timeout object
:param verify: (optional) Either a boolean, in which case it controls whether
we verify the server's TLS certificate, or a string, in which case it
must be a path to a CA bundle to use
:param cert: (optional) Any user-provided SSL certificate to be trusted.
:param proxies: (optional) The proxies dictionary to apply to the request.
:rtype: requests.Response
"""

try:
conn = self._get_connection(request, verify, proxies=proxies, cert=cert)
except LocationValueError as e:
raise InvalidURL(e, request=request)

self.cert_verify(conn, request.url, verify, cert)
url = self.request_url(request, proxies)
self.add_headers(
request,
stream=stream,
timeout=timeout,
verify=verify,
cert=cert,
proxies=proxies,
)

chunked = not (request.body is None or "Content-Length" in request.headers)

if isinstance(timeout, tuple):
try:
connect, read = timeout
timeout = TimeoutSauce(connect=connect, read=read)
except ValueError:
raise ValueError(
f"Invalid timeout {timeout}. Pass a (connect, read) timeout tuple, "
f"or a single float to set both timeouts to the same value."
)
elif isinstance(timeout, TimeoutSauce):
pass
else:
timeout = TimeoutSauce(connect=timeout, read=timeout)

try:
> resp = conn.urlopen(
method=request.method,
url=url,
body=request.body,
headers=request.headers,
redirect=False,
assert_same_host=False,
preload_content=False,
decode_content=False,
retries=self.max_retries,
timeout=timeout,
chunked=chunked,
)

venv/lib/python3.11/site-packages/requests/adapters.py:564:
_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _
venv/lib/python3.11/site-packages/urllib3/connectionpool.py:843: in urlopen
retries = retries.increment(
_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _

self = Retry(total=0, connect=None, read=False, redirect=None, status=None), method = 'POST', url = '/api/v5/addons/upload/', response = None
error = NameResolutionError("<urllib3.connection.HTTPSConnection object at 0x103bc2850>: Failed to resolve 'addons.allizom.org' ([Errno 8] nodename nor servname provided, or not known)")
_pool = <urllib3.connectionpool.HTTPSConnectionPool object at 0x103bc2b10>, _stacktrace = <traceback object at 0x103bc28c0>

def increment(
self,
method: str | None = None,
url: str | None = None,
response: BaseHTTPResponse | None = None,
error: Exception | None = None,
_pool: ConnectionPool | None = None,
_stacktrace: TracebackType | None = None,
) -> Self:
"""Return a new Retry object with incremented retry counters.

:param response: A response object, or None, if the server did not
return a response.
:type response: :class:`~urllib3.response.BaseHTTPResponse`
:param Exception error: An error encountered during the request, or
None if the response was received successfully.

:return: A new ``Retry`` object.
"""
if self.total is False and error:
# Disabled, indicate to re-raise the error.
raise reraise(type(error), error, _stacktrace)

total = self.total
if total is not None:
total -= 1

connect = self.connect
read = self.read
redirect = self.redirect
status_count = self.status
other = self.other
cause = "unknown"
status = None
redirect_location = None

if error and self._is_connection_error(error):
# Connect retry?
if connect is False:
raise reraise(type(error), error, _stacktrace)
elif connect is not None:
connect -= 1

elif error and self._is_read_error(error):
# Read retry?
if read is False or method is None or not self._is_method_retryable(method):
raise reraise(type(error), error, _stacktrace)
elif read is not None:
read -= 1

elif error:
# Other retry?
if other is not None:
other -= 1

elif response and response.get_redirect_location():
# Redirect retry?
if redirect is not None:
redirect -= 1
cause = "too many redirects"
response_redirect_location = response.get_redirect_location()
if response_redirect_location:
redirect_location = response_redirect_location
status = response.status

else:
# Incrementing because of a server error like a 500 in
# status_forcelist and the given method is in the allowed_methods
cause = ResponseError.GENERIC_ERROR
if response and response.status:
if status_count is not None:
status_count -= 1
cause = ResponseError.SPECIFIC_ERROR.format(status_code=response.status)
status = response.status

history = self.history + (
RequestHistory(method, url, error, status, redirect_location),
)

new_retry = self.new(
total=total,
connect=connect,
read=read,
redirect=redirect,
status=status_count,
other=other,
history=history,
)

if new_retry.is_exhausted():
reason = error or ResponseError(cause)
> raise MaxRetryError(_pool, url, reason) from reason # type: ignore[arg-type]
E urllib3.exceptions.MaxRetryError: HTTPSConnectionPool(host='addons.allizom.org', port=443): Max retries exceeded with url: /api/v5/addons/upload/ (Caused by NameResolutionError("<urllib3.connection.HTTPSConnection object at 0x103bc2850>: Failed to resolve 'addons.allizom.org' ([Errno 8] nodename nor servname provided, or not known)"))

venv/lib/python3.11/site-packages/urllib3/util/retry.py:519: MaxRetryError

During handling of the above exception, another exception occurred:

base_url = 'https://addons.allizom.org', session_auth = 'ldvd5ag27bkfpukx6rn2lcj0yuvakt3v', guid = 'reserved_guid@mozilla.com'

@pytest.mark.parametrize(
"guid",
[
"reserved_guid@mozilla.com",
"reserved_guid@mozilla.org",
"reserved_guid@pioneer.mozilla.org",
"reserved_guid@search.mozilla.org",
"reserved_guid@shield.mozilla.com",
"reserved_guid@shield.mozilla.org",
"reserved_guid@mozillaonline.com",
"reserved_guid@mozillafoundation.org",
"reserved_guid@rally.mozilla.org",
"reserved_guid@temporary-addon",
"reserved_guid@mozac.org",
],
)
@pytest.mark.serial
@pytest.mark.create_session("api_user")
def test_submit_addon_with_reserved_guid(base_url, session_auth, guid):
"""Upload an addon that has a reserved guid suffix, unavailable for regular users"""
manifest = {
**payloads.minimal_manifest,
"name": "Reserved guid",
"browser_specific_settings": {"gecko": {"id": guid}},
}
api_helpers.make_addon(manifest)
with open("sample-addons/make-addon.zip", "rb") as file:
> upload = requests.post(
url=f"{base_url}{_upload}",
headers={"Authorization": f"Session {session_auth}"},
files={"upload": file},
data={"channel": "listed"},
)

tests/api_w/test_addon_uploads.py:392:
_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _
venv/lib/python3.11/site-packages/requests/api.py:115: in post
return request("post", url, data=data, json=json, **kwargs)
venv/lib/python3.11/site-packages/requests/api.py:59: in request
return session.request(method=method, url=url, **kwargs)
venv/lib/python3.11/site-packages/requests/sessions.py:589: in request
resp = self.send(prep, **send_kwargs)
venv/lib/python3.11/site-packages/requests/sessions.py:703: in send
r = adapter.send(request, **kwargs)
_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _

self = <requests.adapters.HTTPAdapter object at 0x103bc2bd0>, request = <PreparedRequest [POST]>, stream = False, timeout = Timeout(connect=None, read=None, total=None), verify = True, cert = None
proxies = OrderedDict()

def send(
self, request, stream=False, timeout=None, verify=True, cert=None, proxies=None
):
"""Sends PreparedRequest object. Returns Response object.

:param request: The :class:`PreparedRequest <PreparedRequest>` being sent.
:param stream: (optional) Whether to stream the request content.
:param timeout: (optional) How long to wait for the server to send
data before giving up, as a float, or a :ref:`(connect timeout,
read timeout) <timeouts>` tuple.
:type timeout: float or tuple or urllib3 Timeout object
:param verify: (optional) Either a boolean, in which case it controls whether
we verify the server's TLS certificate, or a string, in which case it
must be a path to a CA bundle to use
:param cert: (optional) Any user-provided SSL certificate to be trusted.
:param proxies: (optional) The proxies dictionary to apply to the request.
:rtype: requests.Response
"""

try:
conn = self._get_connection(request, verify, proxies=proxies, cert=cert)
except LocationValueError as e:
raise InvalidURL(e, request=request)

self.cert_verify(conn, request.url, verify, cert)
url = self.request_url(request, proxies)
self.add_headers(
request,
stream=stream,
timeout=timeout,
verify=verify,
cert=cert,
proxies=proxies,
)

chunked = not (request.body is None or "Content-Length" in request.headers)

if isinstance(timeout, tuple):
try:
connect, read = timeout
timeout = TimeoutSauce(connect=connect, read=read)
except ValueError:
raise ValueError(
f"Invalid timeout {timeout}. Pass a (connect, read) timeout tuple, "
f"or a single float to set both timeouts to the same value."
)
elif isinstance(timeout, TimeoutSauce):
pass
else:
timeout = TimeoutSauce(connect=timeout, read=timeout)

try:
resp = conn.urlopen(
method=request.method,
url=url,
body=request.body,
headers=request.headers,
redirect=False,
assert_same_host=False,
preload_content=False,
decode_content=False,
retries=self.max_retries,
timeout=timeout,
chunked=chunked,
)

except (ProtocolError, OSError) as err:
raise ConnectionError(err, request=request)

except MaxRetryError as e:
if isinstance(e.reason, ConnectTimeoutError):
# TODO: Remove this in 3.0.0: see #2811
if not isinstance(e.reason, NewConnectionError):
raise ConnectTimeout(e, request=request)

if isinstance(e.reason, ResponseError):
raise RetryError(e, request=request)

if isinstance(e.reason, _ProxyError):
raise ProxyError(e, request=request)

if isinstance(e.reason, _SSLError):
# This branch is for urllib3 v1.22 and later.
raise SSLError(e, request=request)

> raise ConnectionError(e, request=request)
E requests.exceptions.ConnectionError: HTTPSConnectionPool(host='addons.allizom.org', port=443): Max retries exceeded with url: /api/v5/addons/upload/ (Caused by NameResolutionError("<urllib3.connection.HTTPSConnection object at 0x103bc2850>: Failed to resolve 'addons.allizom.org' ([Errno 8] nodename nor servname provided, or not known)"))

venv/lib/python3.11/site-packages/requests/adapters.py:597: ConnectionError
------------------------------Captured stdout call------------------------------
Manifest content: {'manifest_version': 2, 'version': '1.0', 'name': 'Reserved guid', 'browser_specific_settings': {'gecko': {'id': 'reserved_guid@mozilla.com'}}}
Failed tests/api_w/test_addon_uploads.py::test_submit_addon_with_reserved_guid[reserved_guid@mozilla.org] 0.01
self = <urllib3.connection.HTTPSConnection object at 0x103be0490>

def _new_conn(self) -> socket.socket:
"""Establish a socket connection and set nodelay settings on it.

:return: New socket connection.
"""
try:
> sock = connection.create_connection(
(self._dns_host, self.port),
self.timeout,
source_address=self.source_address,
socket_options=self.socket_options,
)

venv/lib/python3.11/site-packages/urllib3/connection.py:196:
_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _
venv/lib/python3.11/site-packages/urllib3/util/connection.py:60: in create_connection
for res in socket.getaddrinfo(host, port, family, socket.SOCK_STREAM):
_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _

host = 'addons.allizom.org', port = 443, family = <AddressFamily.AF_UNSPEC: 0>, type = <SocketKind.SOCK_STREAM: 1>, proto = 0, flags = 0

def getaddrinfo(host, port, family=0, type=0, proto=0, flags=0):
"""Resolve host and port into list of address info entries.

Translate the host/port argument into a sequence of 5-tuples that contain
all the necessary arguments for creating a socket connected to that service.
host is a domain name, a string representation of an IPv4/v6 address or
None. port is a string service name such as 'http', a numeric port number or
None. By passing None as the value of host and port, you can pass NULL to
the underlying C API.

The family, type and proto arguments can be optionally specified in order to
narrow the list of addresses returned. Passing zero as a value for each of
these arguments selects the full range of results.
"""
# We override this function since we want to translate the numeric family
# and socket type values to enum constants.
addrlist = []
> for res in _socket.getaddrinfo(host, port, family, type, proto, flags):
E socket.gaierror: [Errno 8] nodename nor servname provided, or not known

/Library/Frameworks/Python.framework/Versions/3.11/lib/python3.11/socket.py:962: gaierror

The above exception was the direct cause of the following exception:

self = <urllib3.connectionpool.HTTPSConnectionPool object at 0x103be2a10>, method = 'POST', url = '/api/v5/addons/upload/'
body = b'--14f4ee445008dde9830f89d92fa23fc4\r\nContent-Disposition: form-data; name="channel"\r\n\r\nlisted\r\n--14f4ee445008...5\x06\x00\x00\x00\x00\x01\x00\x01\x00;\x00\x00\x00\xba\x00\x00\x00\x00\x00\r\n--14f4ee445008dde9830f89d92fa23fc4--\r\n'
headers = {'User-Agent': 'python-requests/2.32.0', 'Accept-Encoding': 'gzip, deflate', 'Accept': '*/*', 'Connection': 'keep-aliv...j0yuvakt3v', 'Content-Length': '513', 'Content-Type': 'multipart/form-data; boundary=14f4ee445008dde9830f89d92fa23fc4'}
retries = Retry(total=0, connect=None, read=False, redirect=None, status=None), redirect = False, assert_same_host = False, timeout = Timeout(connect=None, read=None, total=None), pool_timeout = None
release_conn = False, chunked = False, body_pos = None, preload_content = False, decode_content = False, response_kw = {}
parsed_url = Url(scheme=None, auth=None, host=None, port=None, path='/api/v5/addons/upload/', query=None, fragment=None), destination_scheme = None, conn = None, release_this_conn = True
http_tunnel_required = False, err = None, clean_exit = False

def urlopen( # type: ignore[override]
self,
method: str,
url: str,
body: _TYPE_BODY | None = None,
headers: typing.Mapping[str, str] | None = None,
retries: Retry | bool | int | None = None,
redirect: bool = True,
assert_same_host: bool = True,
timeout: _TYPE_TIMEOUT = _DEFAULT_TIMEOUT,
pool_timeout: int | None = None,
release_conn: bool | None = None,
chunked: bool = False,
body_pos: _TYPE_BODY_POSITION | None = None,
preload_content: bool = True,
decode_content: bool = True,
**response_kw: typing.Any,
) -> BaseHTTPResponse:
"""
Get a connection from the pool and perform an HTTP request. This is the
lowest level call for making a request, so you'll need to specify all
the raw details.

.. note::

More commonly, it's appropriate to use a convenience method
such as :meth:`request`.

.. note::

`release_conn` will only behave as expected if
`preload_content=False` because we want to make
`preload_content=False` the default behaviour someday soon without
breaking backwards compatibility.

:param method:
HTTP request method (such as GET, POST, PUT, etc.)

:param url:
The URL to perform the request on.

:param body:
Data to send in the request body, either :class:`str`, :class:`bytes`,
an iterable of :class:`str`/:class:`bytes`, or a file-like object.

:param headers:
Dictionary of custom headers to send, such as User-Agent,
If-None-Match, etc. If None, pool headers are used. If provided,
these headers completely replace any pool-specific headers.

:param retries:
Configure the number of retries to allow before raising a
:class:`~urllib3.exceptions.MaxRetryError` exception.

If ``None`` (default) will retry 3 times, see ``Retry.DEFAULT``. Pass a
:class:`~urllib3.util.retry.Retry` object for fine-grained control
over different types of retries.
Pass an integer number to retry connection errors that many times,
but no other types of errors. Pass zero to never retry.

If ``False``, then retries are disabled and any exception is raised
immediately. Also, instead of raising a MaxRetryError on redirects,
the redirect response will be returned.

:type retries: :class:`~urllib3.util.retry.Retry`, False, or an int.

:param redirect:
If True, automatically handle redirects (status codes 301, 302,
303, 307, 308). Each redirect counts as a retry. Disabling retries
will disable redirect, too.

:param assert_same_host:
If ``True``, will make sure that the host of the pool requests is
consistent else will raise HostChangedError. When ``False``, you can
use the pool on an HTTP proxy and request foreign hosts.

:param timeout:
If specified, overrides the default timeout for this one
request. It may be a float (in seconds) or an instance of
:class:`urllib3.util.Timeout`.

:param pool_timeout:
If set and the pool is set to block=True, then this method will
block for ``pool_timeout`` seconds and raise EmptyPoolError if no
connection is available within the time period.

:param bool preload_content:
If True, the response's body will be preloaded into memory.

:param bool decode_content:
If True, will attempt to decode the body based on the
'content-encoding' header.

:param release_conn:
If False, then the urlopen call will not release the connection
back into the pool once a response is received (but will release if
you read the entire contents of the response such as when
`preload_content=True`). This is useful if you're not preloading
the response's content immediately. You will need to call
``r.release_conn()`` on the response ``r`` to return the connection
back into the pool. If None, it takes the value of ``preload_content``
which defaults to ``True``.

:param bool chunked:
If True, urllib3 will send the body using chunked transfer
encoding. Otherwise, urllib3 will send the body using the standard
content-length form. Defaults to False.

:param int body_pos:
Position to seek to in file-like body in the event of a retry or
redirect. Typically this won't need to be set because urllib3 will
auto-populate the value when needed.
"""
parsed_url = parse_url(url)
destination_scheme = parsed_url.scheme

if headers is None:
headers = self.headers

if not isinstance(retries, Retry):
retries = Retry.from_int(retries, redirect=redirect, default=self.retries)

if release_conn is None:
release_conn = preload_content

# Check host
if assert_same_host and not self.is_same_host(url):
raise HostChangedError(self, url, retries)

# Ensure that the URL we're connecting to is properly encoded
if url.startswith("/"):
url = to_str(_encode_target(url))
else:
url = to_str(parsed_url.url)

conn = None

# Track whether `conn` needs to be released before
# returning/raising/recursing. Update this variable if necessary, and
# leave `release_conn` constant throughout the function. That way, if
# the function recurses, the original value of `release_conn` will be
# passed down into the recursive call, and its value will be respected.
#
# See issue #651 [1] for details.
#
# [1] <https://github.com/urllib3/urllib3/issues/651>
release_this_conn = release_conn

http_tunnel_required = connection_requires_http_tunnel(
self.proxy, self.proxy_config, destination_scheme
)

# Merge the proxy headers. Only done when not using HTTP CONNECT. We
# have to copy the headers dict so we can safely change it without those
# changes being reflected in anyone else's copy.
if not http_tunnel_required:
headers = headers.copy() # type: ignore[attr-defined]
headers.update(self.proxy_headers) # type: ignore[union-attr]

# Must keep the exception bound to a separate variable or else Python 3
# complains about UnboundLocalError.
err = None

# Keep track of whether we cleanly exited the except block. This
# ensures we do proper cleanup in finally.
clean_exit = False

# Rewind body position, if needed. Record current position
# for future rewinds in the event of a redirect/retry.
body_pos = set_file_position(body, body_pos)

try:
# Request a connection from the queue.
timeout_obj = self._get_timeout(timeout)
conn = self._get_conn(timeout=pool_timeout)

conn.timeout = timeout_obj.connect_timeout # type: ignore[assignment]

# Is this a closed/new connection that requires CONNECT tunnelling?
if self.proxy is not None and http_tunnel_required and conn.is_closed:
try:
self._prepare_proxy(conn)
except (BaseSSLError, OSError, SocketTimeout) as e:
self._raise_timeout(
err=e, url=self.proxy.url, timeout_value=conn.timeout
)
raise

# If we're going to release the connection in ``finally:``, then
# the response doesn't need to know about the connection. Otherwise
# it will also try to release it and we'll have a double-release
# mess.
response_conn = conn if not release_conn else None

# Make the request on the HTTPConnection object
> response = self._make_request(
conn,
method,
url,
timeout=timeout_obj,
body=body,
headers=headers,
chunked=chunked,
retries=retries,
response_conn=response_conn,
preload_content=preload_content,
decode_content=decode_content,
**response_kw,
)

venv/lib/python3.11/site-packages/urllib3/connectionpool.py:789:
_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _
venv/lib/python3.11/site-packages/urllib3/connectionpool.py:490: in _make_request
raise new_e
venv/lib/python3.11/site-packages/urllib3/connectionpool.py:466: in _make_request
self._validate_conn(conn)
venv/lib/python3.11/site-packages/urllib3/connectionpool.py:1095: in _validate_conn
conn.connect()
venv/lib/python3.11/site-packages/urllib3/connection.py:615: in connect
self.sock = sock = self._new_conn()
_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _

self = <urllib3.connection.HTTPSConnection object at 0x103be0490>

def _new_conn(self) -> socket.socket:
"""Establish a socket connection and set nodelay settings on it.

:return: New socket connection.
"""
try:
sock = connection.create_connection(
(self._dns_host, self.port),
self.timeout,
source_address=self.source_address,
socket_options=self.socket_options,
)
except socket.gaierror as e:
> raise NameResolutionError(self.host, self, e) from e
E urllib3.exceptions.NameResolutionError: <urllib3.connection.HTTPSConnection object at 0x103be0490>: Failed to resolve 'addons.allizom.org' ([Errno 8] nodename nor servname provided, or not known)

venv/lib/python3.11/site-packages/urllib3/connection.py:203: NameResolutionError

The above exception was the direct cause of the following exception:

self = <requests.adapters.HTTPAdapter object at 0x103be2210>, request = <PreparedRequest [POST]>, stream = False, timeout = Timeout(connect=None, read=None, total=None), verify = True, cert = None
proxies = OrderedDict()

def send(
self, request, stream=False, timeout=None, verify=True, cert=None, proxies=None
):
"""Sends PreparedRequest object. Returns Response object.

:param request: The :class:`PreparedRequest <PreparedRequest>` being sent.
:param stream: (optional) Whether to stream the request content.
:param timeout: (optional) How long to wait for the server to send
data before giving up, as a float, or a :ref:`(connect timeout,
read timeout) <timeouts>` tuple.
:type timeout: float or tuple or urllib3 Timeout object
:param verify: (optional) Either a boolean, in which case it controls whether
we verify the server's TLS certificate, or a string, in which case it
must be a path to a CA bundle to use
:param cert: (optional) Any user-provided SSL certificate to be trusted.
:param proxies: (optional) The proxies dictionary to apply to the request.
:rtype: requests.Response
"""

try:
conn = self._get_connection(request, verify, proxies=proxies, cert=cert)
except LocationValueError as e:
raise InvalidURL(e, request=request)

self.cert_verify(conn, request.url, verify, cert)
url = self.request_url(request, proxies)
self.add_headers(
request,
stream=stream,
timeout=timeout,
verify=verify,
cert=cert,
proxies=proxies,
)

chunked = not (request.body is None or "Content-Length" in request.headers)

if isinstance(timeout, tuple):
try:
connect, read = timeout
timeout = TimeoutSauce(connect=connect, read=read)
except ValueError:
raise ValueError(
f"Invalid timeout {timeout}. Pass a (connect, read) timeout tuple, "
f"or a single float to set both timeouts to the same value."
)
elif isinstance(timeout, TimeoutSauce):
pass
else:
timeout = TimeoutSauce(connect=timeout, read=timeout)

try:
> resp = conn.urlopen(
method=request.method,
url=url,
body=request.body,
headers=request.headers,
redirect=False,
assert_same_host=False,
preload_content=False,
decode_content=False,
retries=self.max_retries,
timeout=timeout,
chunked=chunked,
)

venv/lib/python3.11/site-packages/requests/adapters.py:564:
_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _
venv/lib/python3.11/site-packages/urllib3/connectionpool.py:843: in urlopen
retries = retries.increment(
_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _

self = Retry(total=0, connect=None, read=False, redirect=None, status=None), method = 'POST', url = '/api/v5/addons/upload/', response = None
error = NameResolutionError("<urllib3.connection.HTTPSConnection object at 0x103be0490>: Failed to resolve 'addons.allizom.org' ([Errno 8] nodename nor servname provided, or not known)")
_pool = <urllib3.connectionpool.HTTPSConnectionPool object at 0x103be2a10>, _stacktrace = <traceback object at 0x103be2680>

def increment(
self,
method: str | None = None,
url: str | None = None,
response: BaseHTTPResponse | None = None,
error: Exception | None = None,
_pool: ConnectionPool | None = None,
_stacktrace: TracebackType | None = None,
) -> Self:
"""Return a new Retry object with incremented retry counters.

:param response: A response object, or None, if the server did not
return a response.
:type response: :class:`~urllib3.response.BaseHTTPResponse`
:param Exception error: An error encountered during the request, or
None if the response was received successfully.

:return: A new ``Retry`` object.
"""
if self.total is False and error:
# Disabled, indicate to re-raise the error.
raise reraise(type(error), error, _stacktrace)

total = self.total
if total is not None:
total -= 1

connect = self.connect
read = self.read
redirect = self.redirect
status_count = self.status
other = self.other
cause = "unknown"
status = None
redirect_location = None

if error and self._is_connection_error(error):
# Connect retry?
if connect is False:
raise reraise(type(error), error, _stacktrace)
elif connect is not None:
connect -= 1

elif error and self._is_read_error(error):
# Read retry?
if read is False or method is None or not self._is_method_retryable(method):
raise reraise(type(error), error, _stacktrace)
elif read is not None:
read -= 1

elif error:
# Other retry?
if other is not None:
other -= 1

elif response and response.get_redirect_location():
# Redirect retry?
if redirect is not None:
redirect -= 1
cause = "too many redirects"
response_redirect_location = response.get_redirect_location()
if response_redirect_location:
redirect_location = response_redirect_location
status = response.status

else:
# Incrementing because of a server error like a 500 in
# status_forcelist and the given method is in the allowed_methods
cause = ResponseError.GENERIC_ERROR
if response and response.status:
if status_count is not None:
status_count -= 1
cause = ResponseError.SPECIFIC_ERROR.format(status_code=response.status)
status = response.status

history = self.history + (
RequestHistory(method, url, error, status, redirect_location),
)

new_retry = self.new(
total=total,
connect=connect,
read=read,
redirect=redirect,
status=status_count,
other=other,
history=history,
)

if new_retry.is_exhausted():
reason = error or ResponseError(cause)
> raise MaxRetryError(_pool, url, reason) from reason # type: ignore[arg-type]
E urllib3.exceptions.MaxRetryError: HTTPSConnectionPool(host='addons.allizom.org', port=443): Max retries exceeded with url: /api/v5/addons/upload/ (Caused by NameResolutionError("<urllib3.connection.HTTPSConnection object at 0x103be0490>: Failed to resolve 'addons.allizom.org' ([Errno 8] nodename nor servname provided, or not known)"))

venv/lib/python3.11/site-packages/urllib3/util/retry.py:519: MaxRetryError

During handling of the above exception, another exception occurred:

base_url = 'https://addons.allizom.org', session_auth = 'ldvd5ag27bkfpukx6rn2lcj0yuvakt3v', guid = 'reserved_guid@mozilla.org'

@pytest.mark.parametrize(
"guid",
[
"reserved_guid@mozilla.com",
"reserved_guid@mozilla.org",
"reserved_guid@pioneer.mozilla.org",
"reserved_guid@search.mozilla.org",
"reserved_guid@shield.mozilla.com",
"reserved_guid@shield.mozilla.org",
"reserved_guid@mozillaonline.com",
"reserved_guid@mozillafoundation.org",
"reserved_guid@rally.mozilla.org",
"reserved_guid@temporary-addon",
"reserved_guid@mozac.org",
],
)
@pytest.mark.serial
@pytest.mark.create_session("api_user")
def test_submit_addon_with_reserved_guid(base_url, session_auth, guid):
"""Upload an addon that has a reserved guid suffix, unavailable for regular users"""
manifest = {
**payloads.minimal_manifest,
"name": "Reserved guid",
"browser_specific_settings": {"gecko": {"id": guid}},
}
api_helpers.make_addon(manifest)
with open("sample-addons/make-addon.zip", "rb") as file:
> upload = requests.post(
url=f"{base_url}{_upload}",
headers={"Authorization": f"Session {session_auth}"},
files={"upload": file},
data={"channel": "listed"},
)

tests/api_w/test_addon_uploads.py:392:
_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _
venv/lib/python3.11/site-packages/requests/api.py:115: in post
return request("post", url, data=data, json=json, **kwargs)
venv/lib/python3.11/site-packages/requests/api.py:59: in request
return session.request(method=method, url=url, **kwargs)
venv/lib/python3.11/site-packages/requests/sessions.py:589: in request
resp = self.send(prep, **send_kwargs)
venv/lib/python3.11/site-packages/requests/sessions.py:703: in send
r = adapter.send(request, **kwargs)
_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _

self = <requests.adapters.HTTPAdapter object at 0x103be2210>, request = <PreparedRequest [POST]>, stream = False, timeout = Timeout(connect=None, read=None, total=None), verify = True, cert = None
proxies = OrderedDict()

def send(
self, request, stream=False, timeout=None, verify=True, cert=None, proxies=None
):
"""Sends PreparedRequest object. Returns Response object.

:param request: The :class:`PreparedRequest <PreparedRequest>` being sent.
:param stream: (optional) Whether to stream the request content.
:param timeout: (optional) How long to wait for the server to send
data before giving up, as a float, or a :ref:`(connect timeout,
read timeout) <timeouts>` tuple.
:type timeout: float or tuple or urllib3 Timeout object
:param verify: (optional) Either a boolean, in which case it controls whether
we verify the server's TLS certificate, or a string, in which case it
must be a path to a CA bundle to use
:param cert: (optional) Any user-provided SSL certificate to be trusted.
:param proxies: (optional) The proxies dictionary to apply to the request.
:rtype: requests.Response
"""

try:
conn = self._get_connection(request, verify, proxies=proxies, cert=cert)
except LocationValueError as e:
raise InvalidURL(e, request=request)

self.cert_verify(conn, request.url, verify, cert)
url = self.request_url(request, proxies)
self.add_headers(
request,
stream=stream,
timeout=timeout,
verify=verify,
cert=cert,
proxies=proxies,
)

chunked = not (request.body is None or "Content-Length" in request.headers)

if isinstance(timeout, tuple):
try:
connect, read = timeout
timeout = TimeoutSauce(connect=connect, read=read)
except ValueError:
raise ValueError(
f"Invalid timeout {timeout}. Pass a (connect, read) timeout tuple, "
f"or a single float to set both timeouts to the same value."
)
elif isinstance(timeout, TimeoutSauce):
pass
else:
timeout = TimeoutSauce(connect=timeout, read=timeout)

try:
resp = conn.urlopen(
method=request.method,
url=url,
body=request.body,
headers=request.headers,
redirect=False,
assert_same_host=False,
preload_content=False,
decode_content=False,
retries=self.max_retries,
timeout=timeout,
chunked=chunked,
)

except (ProtocolError, OSError) as err:
raise ConnectionError(err, request=request)

except MaxRetryError as e:
if isinstance(e.reason, ConnectTimeoutError):
# TODO: Remove this in 3.0.0: see #2811
if not isinstance(e.reason, NewConnectionError):
raise ConnectTimeout(e, request=request)

if isinstance(e.reason, ResponseError):
raise RetryError(e, request=request)

if isinstance(e.reason, _ProxyError):
raise ProxyError(e, request=request)

if isinstance(e.reason, _SSLError):
# This branch is for urllib3 v1.22 and later.
raise SSLError(e, request=request)

> raise ConnectionError(e, request=request)
E requests.exceptions.ConnectionError: HTTPSConnectionPool(host='addons.allizom.org', port=443): Max retries exceeded with url: /api/v5/addons/upload/ (Caused by NameResolutionError("<urllib3.connection.HTTPSConnection object at 0x103be0490>: Failed to resolve 'addons.allizom.org' ([Errno 8] nodename nor servname provided, or not known)"))

venv/lib/python3.11/site-packages/requests/adapters.py:597: ConnectionError
------------------------------Captured stdout call------------------------------
Manifest content: {'manifest_version': 2, 'version': '1.0', 'name': 'Reserved guid', 'browser_specific_settings': {'gecko': {'id': 'reserved_guid@mozilla.org'}}}
Failed tests/api_w/test_addon_uploads.py::test_submit_addon_with_reserved_guid[reserved_guid@pioneer.mozilla.org] 0.02
self = <urllib3.connection.HTTPSConnection object at 0x103fcdcd0>

def _new_conn(self) -> socket.socket:
"""Establish a socket connection and set nodelay settings on it.

:return: New socket connection.
"""
try:
> sock = connection.create_connection(
(self._dns_host, self.port),
self.timeout,
source_address=self.source_address,
socket_options=self.socket_options,
)

venv/lib/python3.11/site-packages/urllib3/connection.py:196:
_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _
venv/lib/python3.11/site-packages/urllib3/util/connection.py:60: in create_connection
for res in socket.getaddrinfo(host, port, family, socket.SOCK_STREAM):
_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _

host = 'addons.allizom.org', port = 443, family = <AddressFamily.AF_UNSPEC: 0>, type = <SocketKind.SOCK_STREAM: 1>, proto = 0, flags = 0

def getaddrinfo(host, port, family=0, type=0, proto=0, flags=0):
"""Resolve host and port into list of address info entries.

Translate the host/port argument into a sequence of 5-tuples that contain
all the necessary arguments for creating a socket connected to that service.
host is a domain name, a string representation of an IPv4/v6 address or
None. port is a string service name such as 'http', a numeric port number or
None. By passing None as the value of host and port, you can pass NULL to
the underlying C API.

The family, type and proto arguments can be optionally specified in order to
narrow the list of addresses returned. Passing zero as a value for each of
these arguments selects the full range of results.
"""
# We override this function since we want to translate the numeric family
# and socket type values to enum constants.
addrlist = []
> for res in _socket.getaddrinfo(host, port, family, type, proto, flags):
E socket.gaierror: [Errno 8] nodename nor servname provided, or not known

/Library/Frameworks/Python.framework/Versions/3.11/lib/python3.11/socket.py:962: gaierror

The above exception was the direct cause of the following exception:

self = <urllib3.connectionpool.HTTPSConnectionPool object at 0x103fcdb50>, method = 'POST', url = '/api/v5/addons/upload/'
body = b'--0a3217a53158079d75de7dd31d674cca\r\nContent-Disposition: form-data; name="channel"\r\n\r\nlisted\r\n--0a3217a53158...5\x06\x00\x00\x00\x00\x01\x00\x01\x00;\x00\x00\x00\xc2\x00\x00\x00\x00\x00\r\n--0a3217a53158079d75de7dd31d674cca--\r\n'
headers = {'User-Agent': 'python-requests/2.32.0', 'Accept-Encoding': 'gzip, deflate', 'Accept': '*/*', 'Connection': 'keep-aliv...j0yuvakt3v', 'Content-Length': '521', 'Content-Type': 'multipart/form-data; boundary=0a3217a53158079d75de7dd31d674cca'}
retries = Retry(total=0, connect=None, read=False, redirect=None, status=None), redirect = False, assert_same_host = False, timeout = Timeout(connect=None, read=None, total=None), pool_timeout = None
release_conn = False, chunked = False, body_pos = None, preload_content = False, decode_content = False, response_kw = {}
parsed_url = Url(scheme=None, auth=None, host=None, port=None, path='/api/v5/addons/upload/', query=None, fragment=None), destination_scheme = None, conn = None, release_this_conn = True
http_tunnel_required = False, err = None, clean_exit = False

def urlopen( # type: ignore[override]
self,
method: str,
url: str,
body: _TYPE_BODY | None = None,
headers: typing.Mapping[str, str] | None = None,
retries: Retry | bool | int | None = None,
redirect: bool = True,
assert_same_host: bool = True,
timeout: _TYPE_TIMEOUT = _DEFAULT_TIMEOUT,
pool_timeout: int | None = None,
release_conn: bool | None = None,
chunked: bool = False,
body_pos: _TYPE_BODY_POSITION | None = None,
preload_content: bool = True,
decode_content: bool = True,
**response_kw: typing.Any,
) -> BaseHTTPResponse:
"""
Get a connection from the pool and perform an HTTP request. This is the
lowest level call for making a request, so you'll need to specify all
the raw details.

.. note::

More commonly, it's appropriate to use a convenience method
such as :meth:`request`.

.. note::

`release_conn` will only behave as expected if
`preload_content=False` because we want to make
`preload_content=False` the default behaviour someday soon without
breaking backwards compatibility.

:param method:
HTTP request method (such as GET, POST, PUT, etc.)

:param url:
The URL to perform the request on.

:param body:
Data to send in the request body, either :class:`str`, :class:`bytes`,
an iterable of :class:`str`/:class:`bytes`, or a file-like object.

:param headers:
Dictionary of custom headers to send, such as User-Agent,
If-None-Match, etc. If None, pool headers are used. If provided,
these headers completely replace any pool-specific headers.

:param retries:
Configure the number of retries to allow before raising a
:class:`~urllib3.exceptions.MaxRetryError` exception.

If ``None`` (default) will retry 3 times, see ``Retry.DEFAULT``. Pass a
:class:`~urllib3.util.retry.Retry` object for fine-grained control
over different types of retries.
Pass an integer number to retry connection errors that many times,
but no other types of errors. Pass zero to never retry.

If ``False``, then retries are disabled and any exception is raised
immediately. Also, instead of raising a MaxRetryError on redirects,
the redirect response will be returned.

:type retries: :class:`~urllib3.util.retry.Retry`, False, or an int.

:param redirect:
If True, automatically handle redirects (status codes 301, 302,
303, 307, 308). Each redirect counts as a retry. Disabling retries
will disable redirect, too.

:param assert_same_host:
If ``True``, will make sure that the host of the pool requests is
consistent else will raise HostChangedError. When ``False``, you can
use the pool on an HTTP proxy and request foreign hosts.

:param timeout:
If specified, overrides the default timeout for this one
request. It may be a float (in seconds) or an instance of
:class:`urllib3.util.Timeout`.

:param pool_timeout:
If set and the pool is set to block=True, then this method will
block for ``pool_timeout`` seconds and raise EmptyPoolError if no
connection is available within the time period.

:param bool preload_content:
If True, the response's body will be preloaded into memory.

:param bool decode_content:
If True, will attempt to decode the body based on the
'content-encoding' header.

:param release_conn:
If False, then the urlopen call will not release the connection
back into the pool once a response is received (but will release if
you read the entire contents of the response such as when
`preload_content=True`). This is useful if you're not preloading
the response's content immediately. You will need to call
``r.release_conn()`` on the response ``r`` to return the connection
back into the pool. If None, it takes the value of ``preload_content``
which defaults to ``True``.

:param bool chunked:
If True, urllib3 will send the body using chunked transfer
encoding. Otherwise, urllib3 will send the body using the standard
content-length form. Defaults to False.

:param int body_pos:
Position to seek to in file-like body in the event of a retry or
redirect. Typically this won't need to be set because urllib3 will
auto-populate the value when needed.
"""
parsed_url = parse_url(url)
destination_scheme = parsed_url.scheme

if headers is None:
headers = self.headers

if not isinstance(retries, Retry):
retries = Retry.from_int(retries, redirect=redirect, default=self.retries)

if release_conn is None:
release_conn = preload_content

# Check host
if assert_same_host and not self.is_same_host(url):
raise HostChangedError(self, url, retries)

# Ensure that the URL we're connecting to is properly encoded
if url.startswith("/"):
url = to_str(_encode_target(url))
else:
url = to_str(parsed_url.url)

conn = None

# Track whether `conn` needs to be released before
# returning/raising/recursing. Update this variable if necessary, and
# leave `release_conn` constant throughout the function. That way, if
# the function recurses, the original value of `release_conn` will be
# passed down into the recursive call, and its value will be respected.
#
# See issue #651 [1] for details.
#
# [1] <https://github.com/urllib3/urllib3/issues/651>
release_this_conn = release_conn

http_tunnel_required = connection_requires_http_tunnel(
self.proxy, self.proxy_config, destination_scheme
)

# Merge the proxy headers. Only done when not using HTTP CONNECT. We
# have to copy the headers dict so we can safely change it without those
# changes being reflected in anyone else's copy.
if not http_tunnel_required:
headers = headers.copy() # type: ignore[attr-defined]
headers.update(self.proxy_headers) # type: ignore[union-attr]

# Must keep the exception bound to a separate variable or else Python 3
# complains about UnboundLocalError.
err = None

# Keep track of whether we cleanly exited the except block. This
# ensures we do proper cleanup in finally.
clean_exit = False

# Rewind body position, if needed. Record current position
# for future rewinds in the event of a redirect/retry.
body_pos = set_file_position(body, body_pos)

try:
# Request a connection from the queue.
timeout_obj = self._get_timeout(timeout)
conn = self._get_conn(timeout=pool_timeout)

conn.timeout = timeout_obj.connect_timeout # type: ignore[assignment]

# Is this a closed/new connection that requires CONNECT tunnelling?
if self.proxy is not None and http_tunnel_required and conn.is_closed:
try:
self._prepare_proxy(conn)
except (BaseSSLError, OSError, SocketTimeout) as e:
self._raise_timeout(
err=e, url=self.proxy.url, timeout_value=conn.timeout
)
raise

# If we're going to release the connection in ``finally:``, then
# the response doesn't need to know about the connection. Otherwise
# it will also try to release it and we'll have a double-release
# mess.
response_conn = conn if not release_conn else None

# Make the request on the HTTPConnection object
> response = self._make_request(
conn,
method,
url,
timeout=timeout_obj,
body=body,
headers=headers,
chunked=chunked,
retries=retries,
response_conn=response_conn,
preload_content=preload_content,
decode_content=decode_content,
**response_kw,
)

venv/lib/python3.11/site-packages/urllib3/connectionpool.py:789:
_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _
venv/lib/python3.11/site-packages/urllib3/connectionpool.py:490: in _make_request
raise new_e
venv/lib/python3.11/site-packages/urllib3/connectionpool.py:466: in _make_request
self._validate_conn(conn)
venv/lib/python3.11/site-packages/urllib3/connectionpool.py:1095: in _validate_conn
conn.connect()
venv/lib/python3.11/site-packages/urllib3/connection.py:615: in connect
self.sock = sock = self._new_conn()
_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _

self = <urllib3.connection.HTTPSConnection object at 0x103fcdcd0>

def _new_conn(self) -> socket.socket:
"""Establish a socket connection and set nodelay settings on it.

:return: New socket connection.
"""
try:
sock = connection.create_connection(
(self._dns_host, self.port),
self.timeout,
source_address=self.source_address,
socket_options=self.socket_options,
)
except socket.gaierror as e:
> raise NameResolutionError(self.host, self, e) from e
E urllib3.exceptions.NameResolutionError: <urllib3.connection.HTTPSConnection object at 0x103fcdcd0>: Failed to resolve 'addons.allizom.org' ([Errno 8] nodename nor servname provided, or not known)

venv/lib/python3.11/site-packages/urllib3/connection.py:203: NameResolutionError

The above exception was the direct cause of the following exception:

self = <requests.adapters.HTTPAdapter object at 0x103fce8d0>, request = <PreparedRequest [POST]>, stream = False, timeout = Timeout(connect=None, read=None, total=None), verify = True, cert = None
proxies = OrderedDict()

def send(
self, request, stream=False, timeout=None, verify=True, cert=None, proxies=None
):
"""Sends PreparedRequest object. Returns Response object.

:param request: The :class:`PreparedRequest <PreparedRequest>` being sent.
:param stream: (optional) Whether to stream the request content.
:param timeout: (optional) How long to wait for the server to send
data before giving up, as a float, or a :ref:`(connect timeout,
read timeout) <timeouts>` tuple.
:type timeout: float or tuple or urllib3 Timeout object
:param verify: (optional) Either a boolean, in which case it controls whether
we verify the server's TLS certificate, or a string, in which case it
must be a path to a CA bundle to use
:param cert: (optional) Any user-provided SSL certificate to be trusted.
:param proxies: (optional) The proxies dictionary to apply to the request.
:rtype: requests.Response
"""

try:
conn = self._get_connection(request, verify, proxies=proxies, cert=cert)
except LocationValueError as e:
raise InvalidURL(e, request=request)

self.cert_verify(conn, request.url, verify, cert)
url = self.request_url(request, proxies)
self.add_headers(
request,
stream=stream,
timeout=timeout,
verify=verify,
cert=cert,
proxies=proxies,
)

chunked = not (request.body is None or "Content-Length" in request.headers)

if isinstance(timeout, tuple):
try:
connect, read = timeout
timeout = TimeoutSauce(connect=connect, read=read)
except ValueError:
raise ValueError(
f"Invalid timeout {timeout}. Pass a (connect, read) timeout tuple, "
f"or a single float to set both timeouts to the same value."
)
elif isinstance(timeout, TimeoutSauce):
pass
else:
timeout = TimeoutSauce(connect=timeout, read=timeout)

try:
> resp = conn.urlopen(
method=request.method,
url=url,
body=request.body,
headers=request.headers,
redirect=False,
assert_same_host=False,
preload_content=False,
decode_content=False,
retries=self.max_retries,
timeout=timeout,
chunked=chunked,
)

venv/lib/python3.11/site-packages/requests/adapters.py:564:
_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _
venv/lib/python3.11/site-packages/urllib3/connectionpool.py:843: in urlopen
retries = retries.increment(
_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _

self = Retry(total=0, connect=None, read=False, redirect=None, status=None), method = 'POST', url = '/api/v5/addons/upload/', response = None
error = NameResolutionError("<urllib3.connection.HTTPSConnection object at 0x103fcdcd0>: Failed to resolve 'addons.allizom.org' ([Errno 8] nodename nor servname provided, or not known)")
_pool = <urllib3.connectionpool.HTTPSConnectionPool object at 0x103fcdb50>, _stacktrace = <traceback object at 0x103fcc780>

def increment(
self,
method: str | None = None,
url: str | None = None,
response: BaseHTTPResponse | None = None,
error: Exception | None = None,
_pool: ConnectionPool | None = None,
_stacktrace: TracebackType | None = None,
) -> Self:
"""Return a new Retry object with incremented retry counters.

:param response: A response object, or None, if the server did not
return a response.
:type response: :class:`~urllib3.response.BaseHTTPResponse`
:param Exception error: An error encountered during the request, or
None if the response was received successfully.

:return: A new ``Retry`` object.
"""
if self.total is False and error:
# Disabled, indicate to re-raise the error.
raise reraise(type(error), error, _stacktrace)

total = self.total
if total is not None:
total -= 1

connect = self.connect
read = self.read
redirect = self.redirect
status_count = self.status
other = self.other
cause = "unknown"
status = None
redirect_location = None

if error and self._is_connection_error(error):
# Connect retry?
if connect is False:
raise reraise(type(error), error, _stacktrace)
elif connect is not None:
connect -= 1

elif error and self._is_read_error(error):
# Read retry?
if read is False or method is None or not self._is_method_retryable(method):
raise reraise(type(error), error, _stacktrace)
elif read is not None:
read -= 1

elif error:
# Other retry?
if other is not None:
other -= 1

elif response and response.get_redirect_location():
# Redirect retry?
if redirect is not None:
redirect -= 1
cause = "too many redirects"
response_redirect_location = response.get_redirect_location()
if response_redirect_location:
redirect_location = response_redirect_location
status = response.status

else:
# Incrementing because of a server error like a 500 in
# status_forcelist and the given method is in the allowed_methods
cause = ResponseError.GENERIC_ERROR
if response and response.status:
if status_count is not None:
status_count -= 1
cause = ResponseError.SPECIFIC_ERROR.format(status_code=response.status)
status = response.status

history = self.history + (
RequestHistory(method, url, error, status, redirect_location),
)

new_retry = self.new(
total=total,
connect=connect,
read=read,
redirect=redirect,
status=status_count,
other=other,
history=history,
)

if new_retry.is_exhausted():
reason = error or ResponseError(cause)
> raise MaxRetryError(_pool, url, reason) from reason # type: ignore[arg-type]
E urllib3.exceptions.MaxRetryError: HTTPSConnectionPool(host='addons.allizom.org', port=443): Max retries exceeded with url: /api/v5/addons/upload/ (Caused by NameResolutionError("<urllib3.connection.HTTPSConnection object at 0x103fcdcd0>: Failed to resolve 'addons.allizom.org' ([Errno 8] nodename nor servname provided, or not known)"))

venv/lib/python3.11/site-packages/urllib3/util/retry.py:519: MaxRetryError

During handling of the above exception, another exception occurred:

base_url = 'https://addons.allizom.org', session_auth = 'ldvd5ag27bkfpukx6rn2lcj0yuvakt3v', guid = 'reserved_guid@pioneer.mozilla.org'

@pytest.mark.parametrize(
"guid",
[
"reserved_guid@mozilla.com",
"reserved_guid@mozilla.org",
"reserved_guid@pioneer.mozilla.org",
"reserved_guid@search.mozilla.org",
"reserved_guid@shield.mozilla.com",
"reserved_guid@shield.mozilla.org",
"reserved_guid@mozillaonline.com",
"reserved_guid@mozillafoundation.org",
"reserved_guid@rally.mozilla.org",
"reserved_guid@temporary-addon",
"reserved_guid@mozac.org",
],
)
@pytest.mark.serial
@pytest.mark.create_session("api_user")
def test_submit_addon_with_reserved_guid(base_url, session_auth, guid):
"""Upload an addon that has a reserved guid suffix, unavailable for regular users"""
manifest = {
**payloads.minimal_manifest,
"name": "Reserved guid",
"browser_specific_settings": {"gecko": {"id": guid}},
}
api_helpers.make_addon(manifest)
with open("sample-addons/make-addon.zip", "rb") as file:
> upload = requests.post(
url=f"{base_url}{_upload}",
headers={"Authorization": f"Session {session_auth}"},
files={"upload": file},
data={"channel": "listed"},
)

tests/api_w/test_addon_uploads.py:392:
_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _
venv/lib/python3.11/site-packages/requests/api.py:115: in post
return request("post", url, data=data, json=json, **kwargs)
venv/lib/python3.11/site-packages/requests/api.py:59: in request
return session.request(method=method, url=url, **kwargs)
venv/lib/python3.11/site-packages/requests/sessions.py:589: in request
resp = self.send(prep, **send_kwargs)
venv/lib/python3.11/site-packages/requests/sessions.py:703: in send
r = adapter.send(request, **kwargs)
_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _

self = <requests.adapters.HTTPAdapter object at 0x103fce8d0>, request = <PreparedRequest [POST]>, stream = False, timeout = Timeout(connect=None, read=None, total=None), verify = True, cert = None
proxies = OrderedDict()

def send(
self, request, stream=False, timeout=None, verify=True, cert=None, proxies=None
):
"""Sends PreparedRequest object. Returns Response object.

:param request: The :class:`PreparedRequest <PreparedRequest>` being sent.
:param stream: (optional) Whether to stream the request content.
:param timeout: (optional) How long to wait for the server to send
data before giving up, as a float, or a :ref:`(connect timeout,
read timeout) <timeouts>` tuple.
:type timeout: float or tuple or urllib3 Timeout object
:param verify: (optional) Either a boolean, in which case it controls whether
we verify the server's TLS certificate, or a string, in which case it
must be a path to a CA bundle to use
:param cert: (optional) Any user-provided SSL certificate to be trusted.
:param proxies: (optional) The proxies dictionary to apply to the request.
:rtype: requests.Response
"""

try:
conn = self._get_connection(request, verify, proxies=proxies, cert=cert)
except LocationValueError as e:
raise InvalidURL(e, request=request)

self.cert_verify(conn, request.url, verify, cert)
url = self.request_url(request, proxies)
self.add_headers(
request,
stream=stream,
timeout=timeout,
verify=verify,
cert=cert,
proxies=proxies,
)

chunked = not (request.body is None or "Content-Length" in request.headers)

if isinstance(timeout, tuple):
try:
connect, read = timeout
timeout = TimeoutSauce(connect=connect, read=read)
except ValueError:
raise ValueError(
f"Invalid timeout {timeout}. Pass a (connect, read) timeout tuple, "
f"or a single float to set both timeouts to the same value."
)
elif isinstance(timeout, TimeoutSauce):
pass
else:
timeout = TimeoutSauce(connect=timeout, read=timeout)

try:
resp = conn.urlopen(
method=request.method,
url=url,
body=request.body,
headers=request.headers,
redirect=False,
assert_same_host=False,
preload_content=False,
decode_content=False,
retries=self.max_retries,
timeout=timeout,
chunked=chunked,
)

except (ProtocolError, OSError) as err:
raise ConnectionError(err, request=request)

except MaxRetryError as e:
if isinstance(e.reason, ConnectTimeoutError):
# TODO: Remove this in 3.0.0: see #2811
if not isinstance(e.reason, NewConnectionError):
raise ConnectTimeout(e, request=request)

if isinstance(e.reason, ResponseError):
raise RetryError(e, request=request)

if isinstance(e.reason, _ProxyError):
raise ProxyError(e, request=request)

if isinstance(e.reason, _SSLError):
# This branch is for urllib3 v1.22 and later.
raise SSLError(e, request=request)

> raise ConnectionError(e, request=request)
E requests.exceptions.ConnectionError: HTTPSConnectionPool(host='addons.allizom.org', port=443): Max retries exceeded with url: /api/v5/addons/upload/ (Caused by NameResolutionError("<urllib3.connection.HTTPSConnection object at 0x103fcdcd0>: Failed to resolve 'addons.allizom.org' ([Errno 8] nodename nor servname provided, or not known)"))

venv/lib/python3.11/site-packages/requests/adapters.py:597: ConnectionError
------------------------------Captured stdout call------------------------------
Manifest content: {'manifest_version': 2, 'version': '1.0', 'name': 'Reserved guid', 'browser_specific_settings': {'gecko': {'id': 'reserved_guid@pioneer.mozilla.org'}}}
Failed tests/api_w/test_addon_uploads.py::test_submit_addon_with_reserved_guid[reserved_guid@search.mozilla.org] 0.00
self = <urllib3.connection.HTTPSConnection object at 0x103b18f10>

def _new_conn(self) -> socket.socket:
"""Establish a socket connection and set nodelay settings on it.

:return: New socket connection.
"""
try:
> sock = connection.create_connection(
(self._dns_host, self.port),
self.timeout,
source_address=self.source_address,
socket_options=self.socket_options,
)

venv/lib/python3.11/site-packages/urllib3/connection.py:196:
_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _
venv/lib/python3.11/site-packages/urllib3/util/connection.py:60: in create_connection
for res in socket.getaddrinfo(host, port, family, socket.SOCK_STREAM):
_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _

host = 'addons.allizom.org', port = 443, family = <AddressFamily.AF_UNSPEC: 0>, type = <SocketKind.SOCK_STREAM: 1>, proto = 0, flags = 0

def getaddrinfo(host, port, family=0, type=0, proto=0, flags=0):
"""Resolve host and port into list of address info entries.

Translate the host/port argument into a sequence of 5-tuples that contain
all the necessary arguments for creating a socket connected to that service.
host is a domain name, a string representation of an IPv4/v6 address or
None. port is a string service name such as 'http', a numeric port number or
None. By passing None as the value of host and port, you can pass NULL to
the underlying C API.

The family, type and proto arguments can be optionally specified in order to
narrow the list of addresses returned. Passing zero as a value for each of
these arguments selects the full range of results.
"""
# We override this function since we want to translate the numeric family
# and socket type values to enum constants.
addrlist = []
> for res in _socket.getaddrinfo(host, port, family, type, proto, flags):
E socket.gaierror: [Errno 8] nodename nor servname provided, or not known

/Library/Frameworks/Python.framework/Versions/3.11/lib/python3.11/socket.py:962: gaierror

The above exception was the direct cause of the following exception:

self = <urllib3.connectionpool.HTTPSConnectionPool object at 0x103b1a190>, method = 'POST', url = '/api/v5/addons/upload/'
body = b'--11271191507fb258594618e38f92e197\r\nContent-Disposition: form-data; name="channel"\r\n\r\nlisted\r\n--11271191507f...5\x06\x00\x00\x00\x00\x01\x00\x01\x00;\x00\x00\x00\xc1\x00\x00\x00\x00\x00\r\n--11271191507fb258594618e38f92e197--\r\n'
headers = {'User-Agent': 'python-requests/2.32.0', 'Accept-Encoding': 'gzip, deflate', 'Accept': '*/*', 'Connection': 'keep-aliv...j0yuvakt3v', 'Content-Length': '520', 'Content-Type': 'multipart/form-data; boundary=11271191507fb258594618e38f92e197'}
retries = Retry(total=0, connect=None, read=False, redirect=None, status=None), redirect = False, assert_same_host = False, timeout = Timeout(connect=None, read=None, total=None), pool_timeout = None
release_conn = False, chunked = False, body_pos = None, preload_content = False, decode_content = False, response_kw = {}
parsed_url = Url(scheme=None, auth=None, host=None, port=None, path='/api/v5/addons/upload/', query=None, fragment=None), destination_scheme = None, conn = None, release_this_conn = True
http_tunnel_required = False, err = None, clean_exit = False

def urlopen( # type: ignore[override]
self,
method: str,
url: str,
body: _TYPE_BODY | None = None,
headers: typing.Mapping[str, str] | None = None,
retries: Retry | bool | int | None = None,
redirect: bool = True,
assert_same_host: bool = True,
timeout: _TYPE_TIMEOUT = _DEFAULT_TIMEOUT,
pool_timeout: int | None = None,
release_conn: bool | None = None,
chunked: bool = False,
body_pos: _TYPE_BODY_POSITION | None = None,
preload_content: bool = True,
decode_content: bool = True,
**response_kw: typing.Any,
) -> BaseHTTPResponse:
"""
Get a connection from the pool and perform an HTTP request. This is the
lowest level call for making a request, so you'll need to specify all
the raw details.

.. note::

More commonly, it's appropriate to use a convenience method
such as :meth:`request`.

.. note::

`release_conn` will only behave as expected if
`preload_content=False` because we want to make
`preload_content=False` the default behaviour someday soon without
breaking backwards compatibility.

:param method:
HTTP request method (such as GET, POST, PUT, etc.)

:param url:
The URL to perform the request on.

:param body:
Data to send in the request body, either :class:`str`, :class:`bytes`,
an iterable of :class:`str`/:class:`bytes`, or a file-like object.

:param headers:
Dictionary of custom headers to send, such as User-Agent,
If-None-Match, etc. If None, pool headers are used. If provided,
these headers completely replace any pool-specific headers.

:param retries:
Configure the number of retries to allow before raising a
:class:`~urllib3.exceptions.MaxRetryError` exception.

If ``None`` (default) will retry 3 times, see ``Retry.DEFAULT``. Pass a
:class:`~urllib3.util.retry.Retry` object for fine-grained control
over different types of retries.
Pass an integer number to retry connection errors that many times,
but no other types of errors. Pass zero to never retry.

If ``False``, then retries are disabled and any exception is raised
immediately. Also, instead of raising a MaxRetryError on redirects,
the redirect response will be returned.

:type retries: :class:`~urllib3.util.retry.Retry`, False, or an int.

:param redirect:
If True, automatically handle redirects (status codes 301, 302,
303, 307, 308). Each redirect counts as a retry. Disabling retries
will disable redirect, too.

:param assert_same_host:
If ``True``, will make sure that the host of the pool requests is
consistent else will raise HostChangedError. When ``False``, you can
use the pool on an HTTP proxy and request foreign hosts.

:param timeout:
If specified, overrides the default timeout for this one
request. It may be a float (in seconds) or an instance of
:class:`urllib3.util.Timeout`.

:param pool_timeout:
If set and the pool is set to block=True, then this method will
block for ``pool_timeout`` seconds and raise EmptyPoolError if no
connection is available within the time period.

:param bool preload_content:
If True, the response's body will be preloaded into memory.

:param bool decode_content:
If True, will attempt to decode the body based on the
'content-encoding' header.

:param release_conn:
If False, then the urlopen call will not release the connection
back into the pool once a response is received (but will release if
you read the entire contents of the response such as when
`preload_content=True`). This is useful if you're not preloading
the response's content immediately. You will need to call
``r.release_conn()`` on the response ``r`` to return the connection
back into the pool. If None, it takes the value of ``preload_content``
which defaults to ``True``.

:param bool chunked:
If True, urllib3 will send the body using chunked transfer
encoding. Otherwise, urllib3 will send the body using the standard
content-length form. Defaults to False.

:param int body_pos:
Position to seek to in file-like body in the event of a retry or
redirect. Typically this won't need to be set because urllib3 will
auto-populate the value when needed.
"""
parsed_url = parse_url(url)
destination_scheme = parsed_url.scheme

if headers is None:
headers = self.headers

if not isinstance(retries, Retry):
retries = Retry.from_int(retries, redirect=redirect, default=self.retries)

if release_conn is None:
release_conn = preload_content

# Check host
if assert_same_host and not self.is_same_host(url):
raise HostChangedError(self, url, retries)

# Ensure that the URL we're connecting to is properly encoded
if url.startswith("/"):
url = to_str(_encode_target(url))
else:
url = to_str(parsed_url.url)

conn = None

# Track whether `conn` needs to be released before
# returning/raising/recursing. Update this variable if necessary, and
# leave `release_conn` constant throughout the function. That way, if
# the function recurses, the original value of `release_conn` will be
# passed down into the recursive call, and its value will be respected.
#
# See issue #651 [1] for details.
#
# [1] <https://github.com/urllib3/urllib3/issues/651>
release_this_conn = release_conn

http_tunnel_required = connection_requires_http_tunnel(
self.proxy, self.proxy_config, destination_scheme
)

# Merge the proxy headers. Only done when not using HTTP CONNECT. We
# have to copy the headers dict so we can safely change it without those
# changes being reflected in anyone else's copy.
if not http_tunnel_required:
headers = headers.copy() # type: ignore[attr-defined]
headers.update(self.proxy_headers) # type: ignore[union-attr]

# Must keep the exception bound to a separate variable or else Python 3
# complains about UnboundLocalError.
err = None

# Keep track of whether we cleanly exited the except block. This
# ensures we do proper cleanup in finally.
clean_exit = False

# Rewind body position, if needed. Record current position
# for future rewinds in the event of a redirect/retry.
body_pos = set_file_position(body, body_pos)

try:
# Request a connection from the queue.
timeout_obj = self._get_timeout(timeout)
conn = self._get_conn(timeout=pool_timeout)

conn.timeout = timeout_obj.connect_timeout # type: ignore[assignment]

# Is this a closed/new connection that requires CONNECT tunnelling?
if self.proxy is not None and http_tunnel_required and conn.is_closed:
try:
self._prepare_proxy(conn)
except (BaseSSLError, OSError, SocketTimeout) as e:
self._raise_timeout(
err=e, url=self.proxy.url, timeout_value=conn.timeout
)
raise

# If we're going to release the connection in ``finally:``, then
# the response doesn't need to know about the connection. Otherwise
# it will also try to release it and we'll have a double-release
# mess.
response_conn = conn if not release_conn else None

# Make the request on the HTTPConnection object
> response = self._make_request(
conn,
method,
url,
timeout=timeout_obj,
body=body,
headers=headers,
chunked=chunked,
retries=retries,
response_conn=response_conn,
preload_content=preload_content,
decode_content=decode_content,
**response_kw,
)

venv/lib/python3.11/site-packages/urllib3/connectionpool.py:789:
_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _
venv/lib/python3.11/site-packages/urllib3/connectionpool.py:490: in _make_request
raise new_e
venv/lib/python3.11/site-packages/urllib3/connectionpool.py:466: in _make_request
self._validate_conn(conn)
venv/lib/python3.11/site-packages/urllib3/connectionpool.py:1095: in _validate_conn
conn.connect()
venv/lib/python3.11/site-packages/urllib3/connection.py:615: in connect
self.sock = sock = self._new_conn()
_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _

self = <urllib3.connection.HTTPSConnection object at 0x103b18f10>

def _new_conn(self) -> socket.socket:
"""Establish a socket connection and set nodelay settings on it.

:return: New socket connection.
"""
try:
sock = connection.create_connection(
(self._dns_host, self.port),
self.timeout,
source_address=self.source_address,
socket_options=self.socket_options,
)
except socket.gaierror as e:
> raise NameResolutionError(self.host, self, e) from e
E urllib3.exceptions.NameResolutionError: <urllib3.connection.HTTPSConnection object at 0x103b18f10>: Failed to resolve 'addons.allizom.org' ([Errno 8] nodename nor servname provided, or not known)

venv/lib/python3.11/site-packages/urllib3/connection.py:203: NameResolutionError

The above exception was the direct cause of the following exception:

self = <requests.adapters.HTTPAdapter object at 0x103b18910>, request = <PreparedRequest [POST]>, stream = False, timeout = Timeout(connect=None, read=None, total=None), verify = True, cert = None
proxies = OrderedDict()

def send(
self, request, stream=False, timeout=None, verify=True, cert=None, proxies=None
):
"""Sends PreparedRequest object. Returns Response object.

:param request: The :class:`PreparedRequest <PreparedRequest>` being sent.
:param stream: (optional) Whether to stream the request content.
:param timeout: (optional) How long to wait for the server to send
data before giving up, as a float, or a :ref:`(connect timeout,
read timeout) <timeouts>` tuple.
:type timeout: float or tuple or urllib3 Timeout object
:param verify: (optional) Either a boolean, in which case it controls whether
we verify the server's TLS certificate, or a string, in which case it
must be a path to a CA bundle to use
:param cert: (optional) Any user-provided SSL certificate to be trusted.
:param proxies: (optional) The proxies dictionary to apply to the request.
:rtype: requests.Response
"""

try:
conn = self._get_connection(request, verify, proxies=proxies, cert=cert)
except LocationValueError as e:
raise InvalidURL(e, request=request)

self.cert_verify(conn, request.url, verify, cert)
url = self.request_url(request, proxies)
self.add_headers(
request,
stream=stream,
timeout=timeout,
verify=verify,
cert=cert,
proxies=proxies,
)

chunked = not (request.body is None or "Content-Length" in request.headers)

if isinstance(timeout, tuple):
try:
connect, read = timeout
timeout = TimeoutSauce(connect=connect, read=read)
except ValueError:
raise ValueError(
f"Invalid timeout {timeout}. Pass a (connect, read) timeout tuple, "
f"or a single float to set both timeouts to the same value."
)
elif isinstance(timeout, TimeoutSauce):
pass
else:
timeout = TimeoutSauce(connect=timeout, read=timeout)

try:
> resp = conn.urlopen(
method=request.method,
url=url,
body=request.body,
headers=request.headers,
redirect=False,
assert_same_host=False,
preload_content=False,
decode_content=False,
retries=self.max_retries,
timeout=timeout,
chunked=chunked,
)

venv/lib/python3.11/site-packages/requests/adapters.py:564:
_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _
venv/lib/python3.11/site-packages/urllib3/connectionpool.py:843: in urlopen
retries = retries.increment(
_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _

self = Retry(total=0, connect=None, read=False, redirect=None, status=None), method = 'POST', url = '/api/v5/addons/upload/', response = None
error = NameResolutionError("<urllib3.connection.HTTPSConnection object at 0x103b18f10>: Failed to resolve 'addons.allizom.org' ([Errno 8] nodename nor servname provided, or not known)")
_pool = <urllib3.connectionpool.HTTPSConnectionPool object at 0x103b1a190>, _stacktrace = <traceback object at 0x103b1aa80>

def increment(
self,
method: str | None = None,
url: str | None = None,
response: BaseHTTPResponse | None = None,
error: Exception | None = None,
_pool: ConnectionPool | None = None,
_stacktrace: TracebackType | None = None,
) -> Self:
"""Return a new Retry object with incremented retry counters.

:param response: A response object, or None, if the server did not
return a response.
:type response: :class:`~urllib3.response.BaseHTTPResponse`
:param Exception error: An error encountered during the request, or
None if the response was received successfully.

:return: A new ``Retry`` object.
"""
if self.total is False and error:
# Disabled, indicate to re-raise the error.
raise reraise(type(error), error, _stacktrace)

total = self.total
if total is not None:
total -= 1

connect = self.connect
read = self.read
redirect = self.redirect
status_count = self.status
other = self.other
cause = "unknown"
status = None
redirect_location = None

if error and self._is_connection_error(error):
# Connect retry?
if connect is False:
raise reraise(type(error), error, _stacktrace)
elif connect is not None:
connect -= 1

elif error and self._is_read_error(error):
# Read retry?
if read is False or method is None or not self._is_method_retryable(method):
raise reraise(type(error), error, _stacktrace)
elif read is not None:
read -= 1

elif error:
# Other retry?
if other is not None:
other -= 1

elif response and response.get_redirect_location():
# Redirect retry?
if redirect is not None:
redirect -= 1
cause = "too many redirects"
response_redirect_location = response.get_redirect_location()
if response_redirect_location:
redirect_location = response_redirect_location
status = response.status

else:
# Incrementing because of a server error like a 500 in
# status_forcelist and the given method is in the allowed_methods
cause = ResponseError.GENERIC_ERROR
if response and response.status:
if status_count is not None:
status_count -= 1
cause = ResponseError.SPECIFIC_ERROR.format(status_code=response.status)
status = response.status

history = self.history + (
RequestHistory(method, url, error, status, redirect_location),
)

new_retry = self.new(
total=total,
connect=connect,
read=read,
redirect=redirect,
status=status_count,
other=other,
history=history,
)

if new_retry.is_exhausted():
reason = error or ResponseError(cause)
> raise MaxRetryError(_pool, url, reason) from reason # type: ignore[arg-type]
E urllib3.exceptions.MaxRetryError: HTTPSConnectionPool(host='addons.allizom.org', port=443): Max retries exceeded with url: /api/v5/addons/upload/ (Caused by NameResolutionError("<urllib3.connection.HTTPSConnection object at 0x103b18f10>: Failed to resolve 'addons.allizom.org' ([Errno 8] nodename nor servname provided, or not known)"))

venv/lib/python3.11/site-packages/urllib3/util/retry.py:519: MaxRetryError

During handling of the above exception, another exception occurred:

base_url = 'https://addons.allizom.org', session_auth = 'ldvd5ag27bkfpukx6rn2lcj0yuvakt3v', guid = 'reserved_guid@search.mozilla.org'

@pytest.mark.parametrize(
"guid",
[
"reserved_guid@mozilla.com",
"reserved_guid@mozilla.org",
"reserved_guid@pioneer.mozilla.org",
"reserved_guid@search.mozilla.org",
"reserved_guid@shield.mozilla.com",
"reserved_guid@shield.mozilla.org",
"reserved_guid@mozillaonline.com",
"reserved_guid@mozillafoundation.org",
"reserved_guid@rally.mozilla.org",
"reserved_guid@temporary-addon",
"reserved_guid@mozac.org",
],
)
@pytest.mark.serial
@pytest.mark.create_session("api_user")
def test_submit_addon_with_reserved_guid(base_url, session_auth, guid):
"""Upload an addon that has a reserved guid suffix, unavailable for regular users"""
manifest = {
**payloads.minimal_manifest,
"name": "Reserved guid",
"browser_specific_settings": {"gecko": {"id": guid}},
}
api_helpers.make_addon(manifest)
with open("sample-addons/make-addon.zip", "rb") as file:
> upload = requests.post(
url=f"{base_url}{_upload}",
headers={"Authorization": f"Session {session_auth}"},
files={"upload": file},
data={"channel": "listed"},
)

tests/api_w/test_addon_uploads.py:392:
_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _
venv/lib/python3.11/site-packages/requests/api.py:115: in post
return request("post", url, data=data, json=json, **kwargs)
venv/lib/python3.11/site-packages/requests/api.py:59: in request
return session.request(method=method, url=url, **kwargs)
venv/lib/python3.11/site-packages/requests/sessions.py:589: in request
resp = self.send(prep, **send_kwargs)
venv/lib/python3.11/site-packages/requests/sessions.py:703: in send
r = adapter.send(request, **kwargs)
_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _

self = <requests.adapters.HTTPAdapter object at 0x103b18910>, request = <PreparedRequest [POST]>, stream = False, timeout = Timeout(connect=None, read=None, total=None), verify = True, cert = None
proxies = OrderedDict()

def send(
self, request, stream=False, timeout=None, verify=True, cert=None, proxies=None
):
"""Sends PreparedRequest object. Returns Response object.

:param request: The :class:`PreparedRequest <PreparedRequest>` being sent.
:param stream: (optional) Whether to stream the request content.
:param timeout: (optional) How long to wait for the server to send
data before giving up, as a float, or a :ref:`(connect timeout,
read timeout) <timeouts>` tuple.
:type timeout: float or tuple or urllib3 Timeout object
:param verify: (optional) Either a boolean, in which case it controls whether
we verify the server's TLS certificate, or a string, in which case it
must be a path to a CA bundle to use
:param cert: (optional) Any user-provided SSL certificate to be trusted.
:param proxies: (optional) The proxies dictionary to apply to the request.
:rtype: requests.Response
"""

try:
conn = self._get_connection(request, verify, proxies=proxies, cert=cert)
except LocationValueError as e:
raise InvalidURL(e, request=request)

self.cert_verify(conn, request.url, verify, cert)
url = self.request_url(request, proxies)
self.add_headers(
request,
stream=stream,
timeout=timeout,
verify=verify,
cert=cert,
proxies=proxies,
)

chunked = not (request.body is None or "Content-Length" in request.headers)

if isinstance(timeout, tuple):
try:
connect, read = timeout
timeout = TimeoutSauce(connect=connect, read=read)
except ValueError:
raise ValueError(
f"Invalid timeout {timeout}. Pass a (connect, read) timeout tuple, "
f"or a single float to set both timeouts to the same value."
)
elif isinstance(timeout, TimeoutSauce):
pass
else:
timeout = TimeoutSauce(connect=timeout, read=timeout)

try:
resp = conn.urlopen(
method=request.method,
url=url,
body=request.body,
headers=request.headers,
redirect=False,
assert_same_host=False,
preload_content=False,
decode_content=False,
retries=self.max_retries,
timeout=timeout,
chunked=chunked,
)

except (ProtocolError, OSError) as err:
raise ConnectionError(err, request=request)

except MaxRetryError as e:
if isinstance(e.reason, ConnectTimeoutError):
# TODO: Remove this in 3.0.0: see #2811
if not isinstance(e.reason, NewConnectionError):
raise ConnectTimeout(e, request=request)

if isinstance(e.reason, ResponseError):
raise RetryError(e, request=request)

if isinstance(e.reason, _ProxyError):
raise ProxyError(e, request=request)

if isinstance(e.reason, _SSLError):
# This branch is for urllib3 v1.22 and later.
raise SSLError(e, request=request)

> raise ConnectionError(e, request=request)
E requests.exceptions.ConnectionError: HTTPSConnectionPool(host='addons.allizom.org', port=443): Max retries exceeded with url: /api/v5/addons/upload/ (Caused by NameResolutionError("<urllib3.connection.HTTPSConnection object at 0x103b18f10>: Failed to resolve 'addons.allizom.org' ([Errno 8] nodename nor servname provided, or not known)"))

venv/lib/python3.11/site-packages/requests/adapters.py:597: ConnectionError
------------------------------Captured stdout call------------------------------
Manifest content: {'manifest_version': 2, 'version': '1.0', 'name': 'Reserved guid', 'browser_specific_settings': {'gecko': {'id': 'reserved_guid@search.mozilla.org'}}}
Failed tests/api_w/test_addon_uploads.py::test_submit_addon_with_reserved_guid[reserved_guid@shield.mozilla.com] 0.01
self = <urllib3.connection.HTTPSConnection object at 0x103d4e590>

def _new_conn(self) -> socket.socket:
"""Establish a socket connection and set nodelay settings on it.

:return: New socket connection.
"""
try:
> sock = connection.create_connection(
(self._dns_host, self.port),
self.timeout,
source_address=self.source_address,
socket_options=self.socket_options,
)

venv/lib/python3.11/site-packages/urllib3/connection.py:196:
_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _
venv/lib/python3.11/site-packages/urllib3/util/connection.py:60: in create_connection
for res in socket.getaddrinfo(host, port, family, socket.SOCK_STREAM):
_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _

host = 'addons.allizom.org', port = 443, family = <AddressFamily.AF_UNSPEC: 0>, type = <SocketKind.SOCK_STREAM: 1>, proto = 0, flags = 0

def getaddrinfo(host, port, family=0, type=0, proto=0, flags=0):
"""Resolve host and port into list of address info entries.

Translate the host/port argument into a sequence of 5-tuples that contain
all the necessary arguments for creating a socket connected to that service.
host is a domain name, a string representation of an IPv4/v6 address or
None. port is a string service name such as 'http', a numeric port number or
None. By passing None as the value of host and port, you can pass NULL to
the underlying C API.

The family, type and proto arguments can be optionally specified in order to
narrow the list of addresses returned. Passing zero as a value for each of
these arguments selects the full range of results.
"""
# We override this function since we want to translate the numeric family
# and socket type values to enum constants.
addrlist = []
> for res in _socket.getaddrinfo(host, port, family, type, proto, flags):
E socket.gaierror: [Errno 8] nodename nor servname provided, or not known

/Library/Frameworks/Python.framework/Versions/3.11/lib/python3.11/socket.py:962: gaierror

The above exception was the direct cause of the following exception:

self = <urllib3.connectionpool.HTTPSConnectionPool object at 0x103d4e410>, method = 'POST', url = '/api/v5/addons/upload/'
body = b'--87f7416da634ace8beb0339c618178be\r\nContent-Disposition: form-data; name="channel"\r\n\r\nlisted\r\n--87f7416da634...5\x06\x00\x00\x00\x00\x01\x00\x01\x00;\x00\x00\x00\xc1\x00\x00\x00\x00\x00\r\n--87f7416da634ace8beb0339c618178be--\r\n'
headers = {'User-Agent': 'python-requests/2.32.0', 'Accept-Encoding': 'gzip, deflate', 'Accept': '*/*', 'Connection': 'keep-aliv...j0yuvakt3v', 'Content-Length': '520', 'Content-Type': 'multipart/form-data; boundary=87f7416da634ace8beb0339c618178be'}
retries = Retry(total=0, connect=None, read=False, redirect=None, status=None), redirect = False, assert_same_host = False, timeout = Timeout(connect=None, read=None, total=None), pool_timeout = None
release_conn = False, chunked = False, body_pos = None, preload_content = False, decode_content = False, response_kw = {}
parsed_url = Url(scheme=None, auth=None, host=None, port=None, path='/api/v5/addons/upload/', query=None, fragment=None), destination_scheme = None, conn = None, release_this_conn = True
http_tunnel_required = False, err = None, clean_exit = False

def urlopen( # type: ignore[override]
self,
method: str,
url: str,
body: _TYPE_BODY | None = None,
headers: typing.Mapping[str, str] | None = None,
retries: Retry | bool | int | None = None,
redirect: bool = True,
assert_same_host: bool = True,
timeout: _TYPE_TIMEOUT = _DEFAULT_TIMEOUT,
pool_timeout: int | None = None,
release_conn: bool | None = None,
chunked: bool = False,
body_pos: _TYPE_BODY_POSITION | None = None,
preload_content: bool = True,
decode_content: bool = True,
**response_kw: typing.Any,
) -> BaseHTTPResponse:
"""
Get a connection from the pool and perform an HTTP request. This is the
lowest level call for making a request, so you'll need to specify all
the raw details.

.. note::

More commonly, it's appropriate to use a convenience method
such as :meth:`request`.

.. note::

`release_conn` will only behave as expected if
`preload_content=False` because we want to make
`preload_content=False` the default behaviour someday soon without
breaking backwards compatibility.

:param method:
HTTP request method (such as GET, POST, PUT, etc.)

:param url:
The URL to perform the request on.

:param body:
Data to send in the request body, either :class:`str`, :class:`bytes`,
an iterable of :class:`str`/:class:`bytes`, or a file-like object.

:param headers:
Dictionary of custom headers to send, such as User-Agent,
If-None-Match, etc. If None, pool headers are used. If provided,
these headers completely replace any pool-specific headers.

:param retries:
Configure the number of retries to allow before raising a
:class:`~urllib3.exceptions.MaxRetryError` exception.

If ``None`` (default) will retry 3 times, see ``Retry.DEFAULT``. Pass a
:class:`~urllib3.util.retry.Retry` object for fine-grained control
over different types of retries.
Pass an integer number to retry connection errors that many times,
but no other types of errors. Pass zero to never retry.

If ``False``, then retries are disabled and any exception is raised
immediately. Also, instead of raising a MaxRetryError on redirects,
the redirect response will be returned.

:type retries: :class:`~urllib3.util.retry.Retry`, False, or an int.

:param redirect:
If True, automatically handle redirects (status codes 301, 302,
303, 307, 308). Each redirect counts as a retry. Disabling retries
will disable redirect, too.

:param assert_same_host:
If ``True``, will make sure that the host of the pool requests is
consistent else will raise HostChangedError. When ``False``, you can
use the pool on an HTTP proxy and request foreign hosts.

:param timeout:
If specified, overrides the default timeout for this one
request. It may be a float (in seconds) or an instance of
:class:`urllib3.util.Timeout`.

:param pool_timeout:
If set and the pool is set to block=True, then this method will
block for ``pool_timeout`` seconds and raise EmptyPoolError if no
connection is available within the time period.

:param bool preload_content:
If True, the response's body will be preloaded into memory.

:param bool decode_content:
If True, will attempt to decode the body based on the
'content-encoding' header.

:param release_conn:
If False, then the urlopen call will not release the connection
back into the pool once a response is received (but will release if
you read the entire contents of the response such as when
`preload_content=True`). This is useful if you're not preloading
the response's content immediately. You will need to call
``r.release_conn()`` on the response ``r`` to return the connection
back into the pool. If None, it takes the value of ``preload_content``
which defaults to ``True``.

:param bool chunked:
If True, urllib3 will send the body using chunked transfer
encoding. Otherwise, urllib3 will send the body using the standard
content-length form. Defaults to False.

:param int body_pos:
Position to seek to in file-like body in the event of a retry or
redirect. Typically this won't need to be set because urllib3 will
auto-populate the value when needed.
"""
parsed_url = parse_url(url)
destination_scheme = parsed_url.scheme

if headers is None:
headers = self.headers

if not isinstance(retries, Retry):
retries = Retry.from_int(retries, redirect=redirect, default=self.retries)

if release_conn is None:
release_conn = preload_content

# Check host
if assert_same_host and not self.is_same_host(url):
raise HostChangedError(self, url, retries)

# Ensure that the URL we're connecting to is properly encoded
if url.startswith("/"):
url = to_str(_encode_target(url))
else:
url = to_str(parsed_url.url)

conn = None

# Track whether `conn` needs to be released before
# returning/raising/recursing. Update this variable if necessary, and
# leave `release_conn` constant throughout the function. That way, if
# the function recurses, the original value of `release_conn` will be
# passed down into the recursive call, and its value will be respected.
#
# See issue #651 [1] for details.
#
# [1] <https://github.com/urllib3/urllib3/issues/651>
release_this_conn = release_conn

http_tunnel_required = connection_requires_http_tunnel(
self.proxy, self.proxy_config, destination_scheme
)

# Merge the proxy headers. Only done when not using HTTP CONNECT. We
# have to copy the headers dict so we can safely change it without those
# changes being reflected in anyone else's copy.
if not http_tunnel_required:
headers = headers.copy() # type: ignore[attr-defined]
headers.update(self.proxy_headers) # type: ignore[union-attr]

# Must keep the exception bound to a separate variable or else Python 3
# complains about UnboundLocalError.
err = None

# Keep track of whether we cleanly exited the except block. This
# ensures we do proper cleanup in finally.
clean_exit = False

# Rewind body position, if needed. Record current position
# for future rewinds in the event of a redirect/retry.
body_pos = set_file_position(body, body_pos)

try:
# Request a connection from the queue.
timeout_obj = self._get_timeout(timeout)
conn = self._get_conn(timeout=pool_timeout)

conn.timeout = timeout_obj.connect_timeout # type: ignore[assignment]

# Is this a closed/new connection that requires CONNECT tunnelling?
if self.proxy is not None and http_tunnel_required and conn.is_closed:
try:
self._prepare_proxy(conn)
except (BaseSSLError, OSError, SocketTimeout) as e:
self._raise_timeout(
err=e, url=self.proxy.url, timeout_value=conn.timeout
)
raise

# If we're going to release the connection in ``finally:``, then
# the response doesn't need to know about the connection. Otherwise
# it will also try to release it and we'll have a double-release
# mess.
response_conn = conn if not release_conn else None

# Make the request on the HTTPConnection object
> response = self._make_request(
conn,
method,
url,
timeout=timeout_obj,
body=body,
headers=headers,
chunked=chunked,
retries=retries,
response_conn=response_conn,
preload_content=preload_content,
decode_content=decode_content,
**response_kw,
)

venv/lib/python3.11/site-packages/urllib3/connectionpool.py:789:
_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _
venv/lib/python3.11/site-packages/urllib3/connectionpool.py:490: in _make_request
raise new_e
venv/lib/python3.11/site-packages/urllib3/connectionpool.py:466: in _make_request
self._validate_conn(conn)
venv/lib/python3.11/site-packages/urllib3/connectionpool.py:1095: in _validate_conn
conn.connect()
venv/lib/python3.11/site-packages/urllib3/connection.py:615: in connect
self.sock = sock = self._new_conn()
_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _

self = <urllib3.connection.HTTPSConnection object at 0x103d4e590>

def _new_conn(self) -> socket.socket:
"""Establish a socket connection and set nodelay settings on it.

:return: New socket connection.
"""
try:
sock = connection.create_connection(
(self._dns_host, self.port),
self.timeout,
source_address=self.source_address,
socket_options=self.socket_options,
)
except socket.gaierror as e:
> raise NameResolutionError(self.host, self, e) from e
E urllib3.exceptions.NameResolutionError: <urllib3.connection.HTTPSConnection object at 0x103d4e590>: Failed to resolve 'addons.allizom.org' ([Errno 8] nodename nor servname provided, or not known)

venv/lib/python3.11/site-packages/urllib3/connection.py:203: NameResolutionError

The above exception was the direct cause of the following exception:

self = <requests.adapters.HTTPAdapter object at 0x103d4c390>, request = <PreparedRequest [POST]>, stream = False, timeout = Timeout(connect=None, read=None, total=None), verify = True, cert = None
proxies = OrderedDict()

def send(
self, request, stream=False, timeout=None, verify=True, cert=None, proxies=None
):
"""Sends PreparedRequest object. Returns Response object.

:param request: The :class:`PreparedRequest <PreparedRequest>` being sent.
:param stream: (optional) Whether to stream the request content.
:param timeout: (optional) How long to wait for the server to send
data before giving up, as a float, or a :ref:`(connect timeout,
read timeout) <timeouts>` tuple.
:type timeout: float or tuple or urllib3 Timeout object
:param verify: (optional) Either a boolean, in which case it controls whether
we verify the server's TLS certificate, or a string, in which case it
must be a path to a CA bundle to use
:param cert: (optional) Any user-provided SSL certificate to be trusted.
:param proxies: (optional) The proxies dictionary to apply to the request.
:rtype: requests.Response
"""

try:
conn = self._get_connection(request, verify, proxies=proxies, cert=cert)
except LocationValueError as e:
raise InvalidURL(e, request=request)

self.cert_verify(conn, request.url, verify, cert)
url = self.request_url(request, proxies)
self.add_headers(
request,
stream=stream,
timeout=timeout,
verify=verify,
cert=cert,
proxies=proxies,
)

chunked = not (request.body is None or "Content-Length" in request.headers)

if isinstance(timeout, tuple):
try:
connect, read = timeout
timeout = TimeoutSauce(connect=connect, read=read)
except ValueError:
raise ValueError(
f"Invalid timeout {timeout}. Pass a (connect, read) timeout tuple, "
f"or a single float to set both timeouts to the same value."
)
elif isinstance(timeout, TimeoutSauce):
pass
else:
timeout = TimeoutSauce(connect=timeout, read=timeout)

try:
> resp = conn.urlopen(
method=request.method,
url=url,
body=request.body,
headers=request.headers,
redirect=False,
assert_same_host=False,
preload_content=False,
decode_content=False,
retries=self.max_retries,
timeout=timeout,
chunked=chunked,
)

venv/lib/python3.11/site-packages/requests/adapters.py:564:
_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _
venv/lib/python3.11/site-packages/urllib3/connectionpool.py:843: in urlopen
retries = retries.increment(
_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _

self = Retry(total=0, connect=None, read=False, redirect=None, status=None), method = 'POST', url = '/api/v5/addons/upload/', response = None
error = NameResolutionError("<urllib3.connection.HTTPSConnection object at 0x103d4e590>: Failed to resolve 'addons.allizom.org' ([Errno 8] nodename nor servname provided, or not known)")
_pool = <urllib3.connectionpool.HTTPSConnectionPool object at 0x103d4e410>, _stacktrace = <traceback object at 0x103d4e480>

def increment(
self,
method: str | None = None,
url: str | None = None,
response: BaseHTTPResponse | None = None,
error: Exception | None = None,
_pool: ConnectionPool | None = None,
_stacktrace: TracebackType | None = None,
) -> Self:
"""Return a new Retry object with incremented retry counters.

:param response: A response object, or None, if the server did not
return a response.
:type response: :class:`~urllib3.response.BaseHTTPResponse`
:param Exception error: An error encountered during the request, or
None if the response was received successfully.

:return: A new ``Retry`` object.
"""
if self.total is False and error:
# Disabled, indicate to re-raise the error.
raise reraise(type(error), error, _stacktrace)

total = self.total
if total is not None:
total -= 1

connect = self.connect
read = self.read
redirect = self.redirect
status_count = self.status
other = self.other
cause = "unknown"
status = None
redirect_location = None

if error and self._is_connection_error(error):
# Connect retry?
if connect is False:
raise reraise(type(error), error, _stacktrace)
elif connect is not None:
connect -= 1

elif error and self._is_read_error(error):
# Read retry?
if read is False or method is None or not self._is_method_retryable(method):
raise reraise(type(error), error, _stacktrace)
elif read is not None:
read -= 1

elif error:
# Other retry?
if other is not None:
other -= 1

elif response and response.get_redirect_location():
# Redirect retry?
if redirect is not None:
redirect -= 1
cause = "too many redirects"
response_redirect_location = response.get_redirect_location()
if response_redirect_location:
redirect_location = response_redirect_location
status = response.status

else:
# Incrementing because of a server error like a 500 in
# status_forcelist and the given method is in the allowed_methods
cause = ResponseError.GENERIC_ERROR
if response and response.status:
if status_count is not None:
status_count -= 1
cause = ResponseError.SPECIFIC_ERROR.format(status_code=response.status)
status = response.status

history = self.history + (
RequestHistory(method, url, error, status, redirect_location),
)

new_retry = self.new(
total=total,
connect=connect,
read=read,
redirect=redirect,
status=status_count,
other=other,
history=history,
)

if new_retry.is_exhausted():
reason = error or ResponseError(cause)
> raise MaxRetryError(_pool, url, reason) from reason # type: ignore[arg-type]
E urllib3.exceptions.MaxRetryError: HTTPSConnectionPool(host='addons.allizom.org', port=443): Max retries exceeded with url: /api/v5/addons/upload/ (Caused by NameResolutionError("<urllib3.connection.HTTPSConnection object at 0x103d4e590>: Failed to resolve 'addons.allizom.org' ([Errno 8] nodename nor servname provided, or not known)"))

venv/lib/python3.11/site-packages/urllib3/util/retry.py:519: MaxRetryError

During handling of the above exception, another exception occurred:

base_url = 'https://addons.allizom.org', session_auth = 'ldvd5ag27bkfpukx6rn2lcj0yuvakt3v', guid = 'reserved_guid@shield.mozilla.com'

@pytest.mark.parametrize(
"guid",
[
"reserved_guid@mozilla.com",
"reserved_guid@mozilla.org",
"reserved_guid@pioneer.mozilla.org",
"reserved_guid@search.mozilla.org",
"reserved_guid@shield.mozilla.com",
"reserved_guid@shield.mozilla.org",
"reserved_guid@mozillaonline.com",
"reserved_guid@mozillafoundation.org",
"reserved_guid@rally.mozilla.org",
"reserved_guid@temporary-addon",
"reserved_guid@mozac.org",
],
)
@pytest.mark.serial
@pytest.mark.create_session("api_user")
def test_submit_addon_with_reserved_guid(base_url, session_auth, guid):
"""Upload an addon that has a reserved guid suffix, unavailable for regular users"""
manifest = {
**payloads.minimal_manifest,
"name": "Reserved guid",
"browser_specific_settings": {"gecko": {"id": guid}},
}
api_helpers.make_addon(manifest)
with open("sample-addons/make-addon.zip", "rb") as file:
> upload = requests.post(
url=f"{base_url}{_upload}",
headers={"Authorization": f"Session {session_auth}"},
files={"upload": file},
data={"channel": "listed"},
)

tests/api_w/test_addon_uploads.py:392:
_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _
venv/lib/python3.11/site-packages/requests/api.py:115: in post
return request("post", url, data=data, json=json, **kwargs)
venv/lib/python3.11/site-packages/requests/api.py:59: in request
return session.request(method=method, url=url, **kwargs)
venv/lib/python3.11/site-packages/requests/sessions.py:589: in request
resp = self.send(prep, **send_kwargs)
venv/lib/python3.11/site-packages/requests/sessions.py:703: in send
r = adapter.send(request, **kwargs)
_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _

self = <requests.adapters.HTTPAdapter object at 0x103d4c390>, request = <PreparedRequest [POST]>, stream = False, timeout = Timeout(connect=None, read=None, total=None), verify = True, cert = None
proxies = OrderedDict()

def send(
self, request, stream=False, timeout=None, verify=True, cert=None, proxies=None
):
"""Sends PreparedRequest object. Returns Response object.

:param request: The :class:`PreparedRequest <PreparedRequest>` being sent.
:param stream: (optional) Whether to stream the request content.
:param timeout: (optional) How long to wait for the server to send
data before giving up, as a float, or a :ref:`(connect timeout,
read timeout) <timeouts>` tuple.
:type timeout: float or tuple or urllib3 Timeout object
:param verify: (optional) Either a boolean, in which case it controls whether
we verify the server's TLS certificate, or a string, in which case it
must be a path to a CA bundle to use
:param cert: (optional) Any user-provided SSL certificate to be trusted.
:param proxies: (optional) The proxies dictionary to apply to the request.
:rtype: requests.Response
"""

try:
conn = self._get_connection(request, verify, proxies=proxies, cert=cert)
except LocationValueError as e:
raise InvalidURL(e, request=request)

self.cert_verify(conn, request.url, verify, cert)
url = self.request_url(request, proxies)
self.add_headers(
request,
stream=stream,
timeout=timeout,
verify=verify,
cert=cert,
proxies=proxies,
)

chunked = not (request.body is None or "Content-Length" in request.headers)

if isinstance(timeout, tuple):
try:
connect, read = timeout
timeout = TimeoutSauce(connect=connect, read=read)
except ValueError:
raise ValueError(
f"Invalid timeout {timeout}. Pass a (connect, read) timeout tuple, "
f"or a single float to set both timeouts to the same value."
)
elif isinstance(timeout, TimeoutSauce):
pass
else:
timeout = TimeoutSauce(connect=timeout, read=timeout)

try:
resp = conn.urlopen(
method=request.method,
url=url,
body=request.body,
headers=request.headers,
redirect=False,
assert_same_host=False,
preload_content=False,
decode_content=False,
retries=self.max_retries,
timeout=timeout,
chunked=chunked,
)

except (ProtocolError, OSError) as err:
raise ConnectionError(err, request=request)

except MaxRetryError as e:
if isinstance(e.reason, ConnectTimeoutError):
# TODO: Remove this in 3.0.0: see #2811
if not isinstance(e.reason, NewConnectionError):
raise ConnectTimeout(e, request=request)

if isinstance(e.reason, ResponseError):
raise RetryError(e, request=request)

if isinstance(e.reason, _ProxyError):
raise ProxyError(e, request=request)

if isinstance(e.reason, _SSLError):
# This branch is for urllib3 v1.22 and later.
raise SSLError(e, request=request)

> raise ConnectionError(e, request=request)
E requests.exceptions.ConnectionError: HTTPSConnectionPool(host='addons.allizom.org', port=443): Max retries exceeded with url: /api/v5/addons/upload/ (Caused by NameResolutionError("<urllib3.connection.HTTPSConnection object at 0x103d4e590>: Failed to resolve 'addons.allizom.org' ([Errno 8] nodename nor servname provided, or not known)"))

venv/lib/python3.11/site-packages/requests/adapters.py:597: ConnectionError
------------------------------Captured stdout call------------------------------
Manifest content: {'manifest_version': 2, 'version': '1.0', 'name': 'Reserved guid', 'browser_specific_settings': {'gecko': {'id': 'reserved_guid@shield.mozilla.com'}}}
Failed tests/api_w/test_addon_uploads.py::test_submit_addon_with_reserved_guid[reserved_guid@shield.mozilla.org] 0.01
self = <urllib3.connection.HTTPSConnection object at 0x10411a750>

def _new_conn(self) -> socket.socket:
"""Establish a socket connection and set nodelay settings on it.

:return: New socket connection.
"""
try:
> sock = connection.create_connection(
(self._dns_host, self.port),
self.timeout,
source_address=self.source_address,
socket_options=self.socket_options,
)

venv/lib/python3.11/site-packages/urllib3/connection.py:196:
_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _
venv/lib/python3.11/site-packages/urllib3/util/connection.py:60: in create_connection
for res in socket.getaddrinfo(host, port, family, socket.SOCK_STREAM):
_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _

host = 'addons.allizom.org', port = 443, family = <AddressFamily.AF_UNSPEC: 0>, type = <SocketKind.SOCK_STREAM: 1>, proto = 0, flags = 0

def getaddrinfo(host, port, family=0, type=0, proto=0, flags=0):
"""Resolve host and port into list of address info entries.

Translate the host/port argument into a sequence of 5-tuples that contain
all the necessary arguments for creating a socket connected to that service.
host is a domain name, a string representation of an IPv4/v6 address or
None. port is a string service name such as 'http', a numeric port number or
None. By passing None as the value of host and port, you can pass NULL to
the underlying C API.

The family, type and proto arguments can be optionally specified in order to
narrow the list of addresses returned. Passing zero as a value for each of
these arguments selects the full range of results.
"""
# We override this function since we want to translate the numeric family
# and socket type values to enum constants.
addrlist = []
> for res in _socket.getaddrinfo(host, port, family, type, proto, flags):
E socket.gaierror: [Errno 8] nodename nor servname provided, or not known

/Library/Frameworks/Python.framework/Versions/3.11/lib/python3.11/socket.py:962: gaierror

The above exception was the direct cause of the following exception:

self = <urllib3.connectionpool.HTTPSConnectionPool object at 0x10411b110>, method = 'POST', url = '/api/v5/addons/upload/'
body = b'--82846cfa26bb092605534d0b2cc70b69\r\nContent-Disposition: form-data; name="channel"\r\n\r\nlisted\r\n--82846cfa26bb...5\x06\x00\x00\x00\x00\x01\x00\x01\x00;\x00\x00\x00\xc1\x00\x00\x00\x00\x00\r\n--82846cfa26bb092605534d0b2cc70b69--\r\n'
headers = {'User-Agent': 'python-requests/2.32.0', 'Accept-Encoding': 'gzip, deflate', 'Accept': '*/*', 'Connection': 'keep-aliv...j0yuvakt3v', 'Content-Length': '520', 'Content-Type': 'multipart/form-data; boundary=82846cfa26bb092605534d0b2cc70b69'}
retries = Retry(total=0, connect=None, read=False, redirect=None, status=None), redirect = False, assert_same_host = False, timeout = Timeout(connect=None, read=None, total=None), pool_timeout = None
release_conn = False, chunked = False, body_pos = None, preload_content = False, decode_content = False, response_kw = {}
parsed_url = Url(scheme=None, auth=None, host=None, port=None, path='/api/v5/addons/upload/', query=None, fragment=None), destination_scheme = None, conn = None, release_this_conn = True
http_tunnel_required = False, err = None, clean_exit = False

def urlopen( # type: ignore[override]
self,
method: str,
url: str,
body: _TYPE_BODY | None = None,
headers: typing.Mapping[str, str] | None = None,
retries: Retry | bool | int | None = None,
redirect: bool = True,
assert_same_host: bool = True,
timeout: _TYPE_TIMEOUT = _DEFAULT_TIMEOUT,
pool_timeout: int | None = None,
release_conn: bool | None = None,
chunked: bool = False,
body_pos: _TYPE_BODY_POSITION | None = None,
preload_content: bool = True,
decode_content: bool = True,
**response_kw: typing.Any,
) -> BaseHTTPResponse:
"""
Get a connection from the pool and perform an HTTP request. This is the
lowest level call for making a request, so you'll need to specify all
the raw details.

.. note::

More commonly, it's appropriate to use a convenience method
such as :meth:`request`.

.. note::

`release_conn` will only behave as expected if
`preload_content=False` because we want to make
`preload_content=False` the default behaviour someday soon without
breaking backwards compatibility.

:param method:
HTTP request method (such as GET, POST, PUT, etc.)

:param url:
The URL to perform the request on.

:param body:
Data to send in the request body, either :class:`str`, :class:`bytes`,
an iterable of :class:`str`/:class:`bytes`, or a file-like object.

:param headers:
Dictionary of custom headers to send, such as User-Agent,
If-None-Match, etc. If None, pool headers are used. If provided,
these headers completely replace any pool-specific headers.

:param retries:
Configure the number of retries to allow before raising a
:class:`~urllib3.exceptions.MaxRetryError` exception.

If ``None`` (default) will retry 3 times, see ``Retry.DEFAULT``. Pass a
:class:`~urllib3.util.retry.Retry` object for fine-grained control
over different types of retries.
Pass an integer number to retry connection errors that many times,
but no other types of errors. Pass zero to never retry.

If ``False``, then retries are disabled and any exception is raised
immediately. Also, instead of raising a MaxRetryError on redirects,
the redirect response will be returned.

:type retries: :class:`~urllib3.util.retry.Retry`, False, or an int.

:param redirect:
If True, automatically handle redirects (status codes 301, 302,
303, 307, 308). Each redirect counts as a retry. Disabling retries
will disable redirect, too.

:param assert_same_host:
If ``True``, will make sure that the host of the pool requests is
consistent else will raise HostChangedError. When ``False``, you can
use the pool on an HTTP proxy and request foreign hosts.

:param timeout:
If specified, overrides the default timeout for this one
request. It may be a float (in seconds) or an instance of
:class:`urllib3.util.Timeout`.

:param pool_timeout:
If set and the pool is set to block=True, then this method will
block for ``pool_timeout`` seconds and raise EmptyPoolError if no
connection is available within the time period.

:param bool preload_content:
If True, the response's body will be preloaded into memory.

:param bool decode_content:
If True, will attempt to decode the body based on the
'content-encoding' header.

:param release_conn:
If False, then the urlopen call will not release the connection
back into the pool once a response is received (but will release if
you read the entire contents of the response such as when
`preload_content=True`). This is useful if you're not preloading
the response's content immediately. You will need to call
``r.release_conn()`` on the response ``r`` to return the connection
back into the pool. If None, it takes the value of ``preload_content``
which defaults to ``True``.

:param bool chunked:
If True, urllib3 will send the body using chunked transfer
encoding. Otherwise, urllib3 will send the body using the standard
content-length form. Defaults to False.

:param int body_pos:
Position to seek to in file-like body in the event of a retry or
redirect. Typically this won't need to be set because urllib3 will
auto-populate the value when needed.
"""
parsed_url = parse_url(url)
destination_scheme = parsed_url.scheme

if headers is None:
headers = self.headers

if not isinstance(retries, Retry):
retries = Retry.from_int(retries, redirect=redirect, default=self.retries)

if release_conn is None:
release_conn = preload_content

# Check host
if assert_same_host and not self.is_same_host(url):
raise HostChangedError(self, url, retries)

# Ensure that the URL we're connecting to is properly encoded
if url.startswith("/"):
url = to_str(_encode_target(url))
else:
url = to_str(parsed_url.url)

conn = None

# Track whether `conn` needs to be released before
# returning/raising/recursing. Update this variable if necessary, and
# leave `release_conn` constant throughout the function. That way, if
# the function recurses, the original value of `release_conn` will be
# passed down into the recursive call, and its value will be respected.
#
# See issue #651 [1] for details.
#
# [1] <https://github.com/urllib3/urllib3/issues/651>
release_this_conn = release_conn

http_tunnel_required = connection_requires_http_tunnel(
self.proxy, self.proxy_config, destination_scheme
)

# Merge the proxy headers. Only done when not using HTTP CONNECT. We
# have to copy the headers dict so we can safely change it without those
# changes being reflected in anyone else's copy.
if not http_tunnel_required:
headers = headers.copy() # type: ignore[attr-defined]
headers.update(self.proxy_headers) # type: ignore[union-attr]

# Must keep the exception bound to a separate variable or else Python 3
# complains about UnboundLocalError.
err = None

# Keep track of whether we cleanly exited the except block. This
# ensures we do proper cleanup in finally.
clean_exit = False

# Rewind body position, if needed. Record current position
# for future rewinds in the event of a redirect/retry.
body_pos = set_file_position(body, body_pos)

try:
# Request a connection from the queue.
timeout_obj = self._get_timeout(timeout)
conn = self._get_conn(timeout=pool_timeout)

conn.timeout = timeout_obj.connect_timeout # type: ignore[assignment]

# Is this a closed/new connection that requires CONNECT tunnelling?
if self.proxy is not None and http_tunnel_required and conn.is_closed:
try:
self._prepare_proxy(conn)
except (BaseSSLError, OSError, SocketTimeout) as e:
self._raise_timeout(
err=e, url=self.proxy.url, timeout_value=conn.timeout
)
raise

# If we're going to release the connection in ``finally:``, then
# the response doesn't need to know about the connection. Otherwise
# it will also try to release it and we'll have a double-release
# mess.
response_conn = conn if not release_conn else None

# Make the request on the HTTPConnection object
> response = self._make_request(
conn,
method,
url,
timeout=timeout_obj,
body=body,
headers=headers,
chunked=chunked,
retries=retries,
response_conn=response_conn,
preload_content=preload_content,
decode_content=decode_content,
**response_kw,
)

venv/lib/python3.11/site-packages/urllib3/connectionpool.py:789:
_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _
venv/lib/python3.11/site-packages/urllib3/connectionpool.py:490: in _make_request
raise new_e
venv/lib/python3.11/site-packages/urllib3/connectionpool.py:466: in _make_request
self._validate_conn(conn)
venv/lib/python3.11/site-packages/urllib3/connectionpool.py:1095: in _validate_conn
conn.connect()
venv/lib/python3.11/site-packages/urllib3/connection.py:615: in connect
self.sock = sock = self._new_conn()
_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _

self = <urllib3.connection.HTTPSConnection object at 0x10411a750>

def _new_conn(self) -> socket.socket:
"""Establish a socket connection and set nodelay settings on it.

:return: New socket connection.
"""
try:
sock = connection.create_connection(
(self._dns_host, self.port),
self.timeout,
source_address=self.source_address,
socket_options=self.socket_options,
)
except socket.gaierror as e:
> raise NameResolutionError(self.host, self, e) from e
E urllib3.exceptions.NameResolutionError: <urllib3.connection.HTTPSConnection object at 0x10411a750>: Failed to resolve 'addons.allizom.org' ([Errno 8] nodename nor servname provided, or not known)

venv/lib/python3.11/site-packages/urllib3/connection.py:203: NameResolutionError

The above exception was the direct cause of the following exception:

self = <requests.adapters.HTTPAdapter object at 0x10411a510>, request = <PreparedRequest [POST]>, stream = False, timeout = Timeout(connect=None, read=None, total=None), verify = True, cert = None
proxies = OrderedDict()

def send(
self, request, stream=False, timeout=None, verify=True, cert=None, proxies=None
):
"""Sends PreparedRequest object. Returns Response object.

:param request: The :class:`PreparedRequest <PreparedRequest>` being sent.
:param stream: (optional) Whether to stream the request content.
:param timeout: (optional) How long to wait for the server to send
data before giving up, as a float, or a :ref:`(connect timeout,
read timeout) <timeouts>` tuple.
:type timeout: float or tuple or urllib3 Timeout object
:param verify: (optional) Either a boolean, in which case it controls whether
we verify the server's TLS certificate, or a string, in which case it
must be a path to a CA bundle to use
:param cert: (optional) Any user-provided SSL certificate to be trusted.
:param proxies: (optional) The proxies dictionary to apply to the request.
:rtype: requests.Response
"""

try:
conn = self._get_connection(request, verify, proxies=proxies, cert=cert)
except LocationValueError as e:
raise InvalidURL(e, request=request)

self.cert_verify(conn, request.url, verify, cert)
url = self.request_url(request, proxies)
self.add_headers(
request,
stream=stream,
timeout=timeout,
verify=verify,
cert=cert,
proxies=proxies,
)

chunked = not (request.body is None or "Content-Length" in request.headers)

if isinstance(timeout, tuple):
try:
connect, read = timeout
timeout = TimeoutSauce(connect=connect, read=read)
except ValueError:
raise ValueError(
f"Invalid timeout {timeout}. Pass a (connect, read) timeout tuple, "
f"or a single float to set both timeouts to the same value."
)
elif isinstance(timeout, TimeoutSauce):
pass
else:
timeout = TimeoutSauce(connect=timeout, read=timeout)

try:
> resp = conn.urlopen(
method=request.method,
url=url,
body=request.body,
headers=request.headers,
redirect=False,
assert_same_host=False,
preload_content=False,
decode_content=False,
retries=self.max_retries,
timeout=timeout,
chunked=chunked,
)

venv/lib/python3.11/site-packages/requests/adapters.py:564:
_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _
venv/lib/python3.11/site-packages/urllib3/connectionpool.py:843: in urlopen
retries = retries.increment(
_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _

self = Retry(total=0, connect=None, read=False, redirect=None, status=None), method = 'POST', url = '/api/v5/addons/upload/', response = None
error = NameResolutionError("<urllib3.connection.HTTPSConnection object at 0x10411a750>: Failed to resolve 'addons.allizom.org' ([Errno 8] nodename nor servname provided, or not known)")
_pool = <urllib3.connectionpool.HTTPSConnectionPool object at 0x10411b110>, _stacktrace = <traceback object at 0x10411a6c0>

def increment(
self,
method: str | None = None,
url: str | None = None,
response: BaseHTTPResponse | None = None,
error: Exception | None = None,
_pool: ConnectionPool | None = None,
_stacktrace: TracebackType | None = None,
) -> Self:
"""Return a new Retry object with incremented retry counters.

:param response: A response object, or None, if the server did not
return a response.
:type response: :class:`~urllib3.response.BaseHTTPResponse`
:param Exception error: An error encountered during the request, or
None if the response was received successfully.

:return: A new ``Retry`` object.
"""
if self.total is False and error:
# Disabled, indicate to re-raise the error.
raise reraise(type(error), error, _stacktrace)

total = self.total
if total is not None:
total -= 1

connect = self.connect
read = self.read
redirect = self.redirect
status_count = self.status
other = self.other
cause = "unknown"
status = None
redirect_location = None

if error and self._is_connection_error(error):
# Connect retry?
if connect is False:
raise reraise(type(error), error, _stacktrace)
elif connect is not None:
connect -= 1

elif error and self._is_read_error(error):
# Read retry?
if read is False or method is None or not self._is_method_retryable(method):
raise reraise(type(error), error, _stacktrace)
elif read is not None:
read -= 1

elif error:
# Other retry?
if other is not None:
other -= 1

elif response and response.get_redirect_location():
# Redirect retry?
if redirect is not None:
redirect -= 1
cause = "too many redirects"
response_redirect_location = response.get_redirect_location()
if response_redirect_location:
redirect_location = response_redirect_location
status = response.status

else:
# Incrementing because of a server error like a 500 in
# status_forcelist and the given method is in the allowed_methods
cause = ResponseError.GENERIC_ERROR
if response and response.status:
if status_count is not None:
status_count -= 1
cause = ResponseError.SPECIFIC_ERROR.format(status_code=response.status)
status = response.status

history = self.history + (
RequestHistory(method, url, error, status, redirect_location),
)

new_retry = self.new(
total=total,
connect=connect,
read=read,
redirect=redirect,
status=status_count,
other=other,
history=history,
)

if new_retry.is_exhausted():
reason = error or ResponseError(cause)
> raise MaxRetryError(_pool, url, reason) from reason # type: ignore[arg-type]
E urllib3.exceptions.MaxRetryError: HTTPSConnectionPool(host='addons.allizom.org', port=443): Max retries exceeded with url: /api/v5/addons/upload/ (Caused by NameResolutionError("<urllib3.connection.HTTPSConnection object at 0x10411a750>: Failed to resolve 'addons.allizom.org' ([Errno 8] nodename nor servname provided, or not known)"))

venv/lib/python3.11/site-packages/urllib3/util/retry.py:519: MaxRetryError

During handling of the above exception, another exception occurred:

base_url = 'https://addons.allizom.org', session_auth = 'ldvd5ag27bkfpukx6rn2lcj0yuvakt3v', guid = 'reserved_guid@shield.mozilla.org'

@pytest.mark.parametrize(
"guid",
[
"reserved_guid@mozilla.com",
"reserved_guid@mozilla.org",
"reserved_guid@pioneer.mozilla.org",
"reserved_guid@search.mozilla.org",
"reserved_guid@shield.mozilla.com",
"reserved_guid@shield.mozilla.org",
"reserved_guid@mozillaonline.com",
"reserved_guid@mozillafoundation.org",
"reserved_guid@rally.mozilla.org",
"reserved_guid@temporary-addon",
"reserved_guid@mozac.org",
],
)
@pytest.mark.serial
@pytest.mark.create_session("api_user")
def test_submit_addon_with_reserved_guid(base_url, session_auth, guid):
"""Upload an addon that has a reserved guid suffix, unavailable for regular users"""
manifest = {
**payloads.minimal_manifest,
"name": "Reserved guid",
"browser_specific_settings": {"gecko": {"id": guid}},
}
api_helpers.make_addon(manifest)
with open("sample-addons/make-addon.zip", "rb") as file:
> upload = requests.post(
url=f"{base_url}{_upload}",
headers={"Authorization": f"Session {session_auth}"},
files={"upload": file},
data={"channel": "listed"},
)

tests/api_w/test_addon_uploads.py:392:
_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _
venv/lib/python3.11/site-packages/requests/api.py:115: in post
return request("post", url, data=data, json=json, **kwargs)
venv/lib/python3.11/site-packages/requests/api.py:59: in request
return session.request(method=method, url=url, **kwargs)
venv/lib/python3.11/site-packages/requests/sessions.py:589: in request
resp = self.send(prep, **send_kwargs)
venv/lib/python3.11/site-packages/requests/sessions.py:703: in send
r = adapter.send(request, **kwargs)
_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _

self = <requests.adapters.HTTPAdapter object at 0x10411a510>, request = <PreparedRequest [POST]>, stream = False, timeout = Timeout(connect=None, read=None, total=None), verify = True, cert = None
proxies = OrderedDict()

def send(
self, request, stream=False, timeout=None, verify=True, cert=None, proxies=None
):
"""Sends PreparedRequest object. Returns Response object.

:param request: The :class:`PreparedRequest <PreparedRequest>` being sent.
:param stream: (optional) Whether to stream the request content.
:param timeout: (optional) How long to wait for the server to send
data before giving up, as a float, or a :ref:`(connect timeout,
read timeout) <timeouts>` tuple.
:type timeout: float or tuple or urllib3 Timeout object
:param verify: (optional) Either a boolean, in which case it controls whether
we verify the server's TLS certificate, or a string, in which case it
must be a path to a CA bundle to use
:param cert: (optional) Any user-provided SSL certificate to be trusted.
:param proxies: (optional) The proxies dictionary to apply to the request.
:rtype: requests.Response
"""

try:
conn = self._get_connection(request, verify, proxies=proxies, cert=cert)
except LocationValueError as e:
raise InvalidURL(e, request=request)

self.cert_verify(conn, request.url, verify, cert)
url = self.request_url(request, proxies)
self.add_headers(
request,
stream=stream,
timeout=timeout,
verify=verify,
cert=cert,
proxies=proxies,
)

chunked = not (request.body is None or "Content-Length" in request.headers)

if isinstance(timeout, tuple):
try:
connect, read = timeout
timeout = TimeoutSauce(connect=connect, read=read)
except ValueError:
raise ValueError(
f"Invalid timeout {timeout}. Pass a (connect, read) timeout tuple, "
f"or a single float to set both timeouts to the same value."
)
elif isinstance(timeout, TimeoutSauce):
pass
else:
timeout = TimeoutSauce(connect=timeout, read=timeout)

try:
resp = conn.urlopen(
method=request.method,
url=url,
body=request.body,
headers=request.headers,
redirect=False,
assert_same_host=False,
preload_content=False,
decode_content=False,
retries=self.max_retries,
timeout=timeout,
chunked=chunked,
)

except (ProtocolError, OSError) as err:
raise ConnectionError(err, request=request)

except MaxRetryError as e:
if isinstance(e.reason, ConnectTimeoutError):
# TODO: Remove this in 3.0.0: see #2811
if not isinstance(e.reason, NewConnectionError):
raise ConnectTimeout(e, request=request)

if isinstance(e.reason, ResponseError):
raise RetryError(e, request=request)

if isinstance(e.reason, _ProxyError):
raise ProxyError(e, request=request)

if isinstance(e.reason, _SSLError):
# This branch is for urllib3 v1.22 and later.
raise SSLError(e, request=request)

> raise ConnectionError(e, request=request)
E requests.exceptions.ConnectionError: HTTPSConnectionPool(host='addons.allizom.org', port=443): Max retries exceeded with url: /api/v5/addons/upload/ (Caused by NameResolutionError("<urllib3.connection.HTTPSConnection object at 0x10411a750>: Failed to resolve 'addons.allizom.org' ([Errno 8] nodename nor servname provided, or not known)"))

venv/lib/python3.11/site-packages/requests/adapters.py:597: ConnectionError
------------------------------Captured stdout call------------------------------
Manifest content: {'manifest_version': 2, 'version': '1.0', 'name': 'Reserved guid', 'browser_specific_settings': {'gecko': {'id': 'reserved_guid@shield.mozilla.org'}}}
Failed tests/api_w/test_addon_uploads.py::test_submit_addon_with_reserved_guid[reserved_guid@mozillaonline.com] 0.01
self = <urllib3.connection.HTTPSConnection object at 0x103c5d790>

def _new_conn(self) -> socket.socket:
"""Establish a socket connection and set nodelay settings on it.

:return: New socket connection.
"""
try:
> sock = connection.create_connection(
(self._dns_host, self.port),
self.timeout,
source_address=self.source_address,
socket_options=self.socket_options,
)

venv/lib/python3.11/site-packages/urllib3/connection.py:196:
_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _
venv/lib/python3.11/site-packages/urllib3/util/connection.py:60: in create_connection
for res in socket.getaddrinfo(host, port, family, socket.SOCK_STREAM):
_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _

host = 'addons.allizom.org', port = 443, family = <AddressFamily.AF_UNSPEC: 0>, type = <SocketKind.SOCK_STREAM: 1>, proto = 0, flags = 0

def getaddrinfo(host, port, family=0, type=0, proto=0, flags=0):
"""Resolve host and port into list of address info entries.

Translate the host/port argument into a sequence of 5-tuples that contain
all the necessary arguments for creating a socket connected to that service.
host is a domain name, a string representation of an IPv4/v6 address or
None. port is a string service name such as 'http', a numeric port number or
None. By passing None as the value of host and port, you can pass NULL to
the underlying C API.

The family, type and proto arguments can be optionally specified in order to
narrow the list of addresses returned. Passing zero as a value for each of
these arguments selects the full range of results.
"""
# We override this function since we want to translate the numeric family
# and socket type values to enum constants.
addrlist = []
> for res in _socket.getaddrinfo(host, port, family, type, proto, flags):
E socket.gaierror: [Errno 8] nodename nor servname provided, or not known

/Library/Frameworks/Python.framework/Versions/3.11/lib/python3.11/socket.py:962: gaierror

The above exception was the direct cause of the following exception:

self = <urllib3.connectionpool.HTTPSConnectionPool object at 0x103c5d450>, method = 'POST', url = '/api/v5/addons/upload/'
body = b'--b25e3c187c701ce981d61cf19becabc2\r\nContent-Disposition: form-data; name="channel"\r\n\r\nlisted\r\n--b25e3c187c70...5\x06\x00\x00\x00\x00\x01\x00\x01\x00;\x00\x00\x00\xc0\x00\x00\x00\x00\x00\r\n--b25e3c187c701ce981d61cf19becabc2--\r\n'
headers = {'User-Agent': 'python-requests/2.32.0', 'Accept-Encoding': 'gzip, deflate', 'Accept': '*/*', 'Connection': 'keep-aliv...j0yuvakt3v', 'Content-Length': '519', 'Content-Type': 'multipart/form-data; boundary=b25e3c187c701ce981d61cf19becabc2'}
retries = Retry(total=0, connect=None, read=False, redirect=None, status=None), redirect = False, assert_same_host = False, timeout = Timeout(connect=None, read=None, total=None), pool_timeout = None
release_conn = False, chunked = False, body_pos = None, preload_content = False, decode_content = False, response_kw = {}
parsed_url = Url(scheme=None, auth=None, host=None, port=None, path='/api/v5/addons/upload/', query=None, fragment=None), destination_scheme = None, conn = None, release_this_conn = True
http_tunnel_required = False, err = None, clean_exit = False

def urlopen( # type: ignore[override]
self,
method: str,
url: str,
body: _TYPE_BODY | None = None,
headers: typing.Mapping[str, str] | None = None,
retries: Retry | bool | int | None = None,
redirect: bool = True,
assert_same_host: bool = True,
timeout: _TYPE_TIMEOUT = _DEFAULT_TIMEOUT,
pool_timeout: int | None = None,
release_conn: bool | None = None,
chunked: bool = False,
body_pos: _TYPE_BODY_POSITION | None = None,
preload_content: bool = True,
decode_content: bool = True,
**response_kw: typing.Any,
) -> BaseHTTPResponse:
"""
Get a connection from the pool and perform an HTTP request. This is the
lowest level call for making a request, so you'll need to specify all
the raw details.

.. note::

More commonly, it's appropriate to use a convenience method
such as :meth:`request`.

.. note::

`release_conn` will only behave as expected if
`preload_content=False` because we want to make
`preload_content=False` the default behaviour someday soon without
breaking backwards compatibility.

:param method:
HTTP request method (such as GET, POST, PUT, etc.)

:param url:
The URL to perform the request on.

:param body:
Data to send in the request body, either :class:`str`, :class:`bytes`,
an iterable of :class:`str`/:class:`bytes`, or a file-like object.

:param headers:
Dictionary of custom headers to send, such as User-Agent,
If-None-Match, etc. If None, pool headers are used. If provided,
these headers completely replace any pool-specific headers.

:param retries:
Configure the number of retries to allow before raising a
:class:`~urllib3.exceptions.MaxRetryError` exception.

If ``None`` (default) will retry 3 times, see ``Retry.DEFAULT``. Pass a
:class:`~urllib3.util.retry.Retry` object for fine-grained control
over different types of retries.
Pass an integer number to retry connection errors that many times,
but no other types of errors. Pass zero to never retry.

If ``False``, then retries are disabled and any exception is raised
immediately. Also, instead of raising a MaxRetryError on redirects,
the redirect response will be returned.

:type retries: :class:`~urllib3.util.retry.Retry`, False, or an int.

:param redirect:
If True, automatically handle redirects (status codes 301, 302,
303, 307, 308). Each redirect counts as a retry. Disabling retries
will disable redirect, too.

:param assert_same_host:
If ``True``, will make sure that the host of the pool requests is
consistent else will raise HostChangedError. When ``False``, you can
use the pool on an HTTP proxy and request foreign hosts.

:param timeout:
If specified, overrides the default timeout for this one
request. It may be a float (in seconds) or an instance of
:class:`urllib3.util.Timeout`.

:param pool_timeout:
If set and the pool is set to block=True, then this method will
block for ``pool_timeout`` seconds and raise EmptyPoolError if no
connection is available within the time period.

:param bool preload_content:
If True, the response's body will be preloaded into memory.

:param bool decode_content:
If True, will attempt to decode the body based on the
'content-encoding' header.

:param release_conn:
If False, then the urlopen call will not release the connection
back into the pool once a response is received (but will release if
you read the entire contents of the response such as when
`preload_content=True`). This is useful if you're not preloading
the response's content immediately. You will need to call
``r.release_conn()`` on the response ``r`` to return the connection
back into the pool. If None, it takes the value of ``preload_content``
which defaults to ``True``.

:param bool chunked:
If True, urllib3 will send the body using chunked transfer
encoding. Otherwise, urllib3 will send the body using the standard
content-length form. Defaults to False.

:param int body_pos:
Position to seek to in file-like body in the event of a retry or
redirect. Typically this won't need to be set because urllib3 will
auto-populate the value when needed.
"""
parsed_url = parse_url(url)
destination_scheme = parsed_url.scheme

if headers is None:
headers = self.headers

if not isinstance(retries, Retry):
retries = Retry.from_int(retries, redirect=redirect, default=self.retries)

if release_conn is None:
release_conn = preload_content

# Check host
if assert_same_host and not self.is_same_host(url):
raise HostChangedError(self, url, retries)

# Ensure that the URL we're connecting to is properly encoded
if url.startswith("/"):
url = to_str(_encode_target(url))
else:
url = to_str(parsed_url.url)

conn = None

# Track whether `conn` needs to be released before
# returning/raising/recursing. Update this variable if necessary, and
# leave `release_conn` constant throughout the function. That way, if
# the function recurses, the original value of `release_conn` will be
# passed down into the recursive call, and its value will be respected.
#
# See issue #651 [1] for details.
#
# [1] <https://github.com/urllib3/urllib3/issues/651>
release_this_conn = release_conn

http_tunnel_required = connection_requires_http_tunnel(
self.proxy, self.proxy_config, destination_scheme
)

# Merge the proxy headers. Only done when not using HTTP CONNECT. We
# have to copy the headers dict so we can safely change it without those
# changes being reflected in anyone else's copy.
if not http_tunnel_required:
headers = headers.copy() # type: ignore[attr-defined]
headers.update(self.proxy_headers) # type: ignore[union-attr]

# Must keep the exception bound to a separate variable or else Python 3
# complains about UnboundLocalError.
err = None

# Keep track of whether we cleanly exited the except block. This
# ensures we do proper cleanup in finally.
clean_exit = False

# Rewind body position, if needed. Record current position
# for future rewinds in the event of a redirect/retry.
body_pos = set_file_position(body, body_pos)

try:
# Request a connection from the queue.
timeout_obj = self._get_timeout(timeout)
conn = self._get_conn(timeout=pool_timeout)

conn.timeout = timeout_obj.connect_timeout # type: ignore[assignment]

# Is this a closed/new connection that requires CONNECT tunnelling?
if self.proxy is not None and http_tunnel_required and conn.is_closed:
try:
self._prepare_proxy(conn)
except (BaseSSLError, OSError, SocketTimeout) as e:
self._raise_timeout(
err=e, url=self.proxy.url, timeout_value=conn.timeout
)
raise

# If we're going to release the connection in ``finally:``, then
# the response doesn't need to know about the connection. Otherwise
# it will also try to release it and we'll have a double-release
# mess.
response_conn = conn if not release_conn else None

# Make the request on the HTTPConnection object
> response = self._make_request(
conn,
method,
url,
timeout=timeout_obj,
body=body,
headers=headers,
chunked=chunked,
retries=retries,
response_conn=response_conn,
preload_content=preload_content,
decode_content=decode_content,
**response_kw,
)

venv/lib/python3.11/site-packages/urllib3/connectionpool.py:789:
_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _
venv/lib/python3.11/site-packages/urllib3/connectionpool.py:490: in _make_request
raise new_e
venv/lib/python3.11/site-packages/urllib3/connectionpool.py:466: in _make_request
self._validate_conn(conn)
venv/lib/python3.11/site-packages/urllib3/connectionpool.py:1095: in _validate_conn
conn.connect()
venv/lib/python3.11/site-packages/urllib3/connection.py:615: in connect
self.sock = sock = self._new_conn()
_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _

self = <urllib3.connection.HTTPSConnection object at 0x103c5d790>

def _new_conn(self) -> socket.socket:
"""Establish a socket connection and set nodelay settings on it.

:return: New socket connection.
"""
try:
sock = connection.create_connection(
(self._dns_host, self.port),
self.timeout,
source_address=self.source_address,
socket_options=self.socket_options,
)
except socket.gaierror as e:
> raise NameResolutionError(self.host, self, e) from e
E urllib3.exceptions.NameResolutionError: <urllib3.connection.HTTPSConnection object at 0x103c5d790>: Failed to resolve 'addons.allizom.org' ([Errno 8] nodename nor servname provided, or not known)

venv/lib/python3.11/site-packages/urllib3/connection.py:203: NameResolutionError

The above exception was the direct cause of the following exception:

self = <requests.adapters.HTTPAdapter object at 0x103c5f510>, request = <PreparedRequest [POST]>, stream = False, timeout = Timeout(connect=None, read=None, total=None), verify = True, cert = None
proxies = OrderedDict()

def send(
self, request, stream=False, timeout=None, verify=True, cert=None, proxies=None
):
"""Sends PreparedRequest object. Returns Response object.

:param request: The :class:`PreparedRequest <PreparedRequest>` being sent.
:param stream: (optional) Whether to stream the request content.
:param timeout: (optional) How long to wait for the server to send
data before giving up, as a float, or a :ref:`(connect timeout,
read timeout) <timeouts>` tuple.
:type timeout: float or tuple or urllib3 Timeout object
:param verify: (optional) Either a boolean, in which case it controls whether
we verify the server's TLS certificate, or a string, in which case it
must be a path to a CA bundle to use
:param cert: (optional) Any user-provided SSL certificate to be trusted.
:param proxies: (optional) The proxies dictionary to apply to the request.
:rtype: requests.Response
"""

try:
conn = self._get_connection(request, verify, proxies=proxies, cert=cert)
except LocationValueError as e:
raise InvalidURL(e, request=request)

self.cert_verify(conn, request.url, verify, cert)
url = self.request_url(request, proxies)
self.add_headers(
request,
stream=stream,
timeout=timeout,
verify=verify,
cert=cert,
proxies=proxies,
)

chunked = not (request.body is None or "Content-Length" in request.headers)

if isinstance(timeout, tuple):
try:
connect, read = timeout
timeout = TimeoutSauce(connect=connect, read=read)
except ValueError:
raise ValueError(
f"Invalid timeout {timeout}. Pass a (connect, read) timeout tuple, "
f"or a single float to set both timeouts to the same value."
)
elif isinstance(timeout, TimeoutSauce):
pass
else:
timeout = TimeoutSauce(connect=timeout, read=timeout)

try:
> resp = conn.urlopen(
method=request.method,
url=url,
body=request.body,
headers=request.headers,
redirect=False,
assert_same_host=False,
preload_content=False,
decode_content=False,
retries=self.max_retries,
timeout=timeout,
chunked=chunked,
)

venv/lib/python3.11/site-packages/requests/adapters.py:564:
_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _
venv/lib/python3.11/site-packages/urllib3/connectionpool.py:843: in urlopen
retries = retries.increment(
_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _

self = Retry(total=0, connect=None, read=False, redirect=None, status=None), method = 'POST', url = '/api/v5/addons/upload/', response = None
error = NameResolutionError("<urllib3.connection.HTTPSConnection object at 0x103c5d790>: Failed to resolve 'addons.allizom.org' ([Errno 8] nodename nor servname provided, or not known)")
_pool = <urllib3.connectionpool.HTTPSConnectionPool object at 0x103c5d450>, _stacktrace = <traceback object at 0x103c5d7c0>

def increment(
self,
method: str | None = None,
url: str | None = None,
response: BaseHTTPResponse | None = None,
error: Exception | None = None,
_pool: ConnectionPool | None = None,
_stacktrace: TracebackType | None = None,
) -> Self:
"""Return a new Retry object with incremented retry counters.

:param response: A response object, or None, if the server did not
return a response.
:type response: :class:`~urllib3.response.BaseHTTPResponse`
:param Exception error: An error encountered during the request, or
None if the response was received successfully.

:return: A new ``Retry`` object.
"""
if self.total is False and error:
# Disabled, indicate to re-raise the error.
raise reraise(type(error), error, _stacktrace)

total = self.total
if total is not None:
total -= 1

connect = self.connect
read = self.read
redirect = self.redirect
status_count = self.status
other = self.other
cause = "unknown"
status = None
redirect_location = None

if error and self._is_connection_error(error):
# Connect retry?
if connect is False:
raise reraise(type(error), error, _stacktrace)
elif connect is not None:
connect -= 1

elif error and self._is_read_error(error):
# Read retry?
if read is False or method is None or not self._is_method_retryable(method):
raise reraise(type(error), error, _stacktrace)
elif read is not None:
read -= 1

elif error:
# Other retry?
if other is not None:
other -= 1

elif response and response.get_redirect_location():
# Redirect retry?
if redirect is not None:
redirect -= 1
cause = "too many redirects"
response_redirect_location = response.get_redirect_location()
if response_redirect_location:
redirect_location = response_redirect_location
status = response.status

else:
# Incrementing because of a server error like a 500 in
# status_forcelist and the given method is in the allowed_methods
cause = ResponseError.GENERIC_ERROR
if response and response.status:
if status_count is not None:
status_count -= 1
cause = ResponseError.SPECIFIC_ERROR.format(status_code=response.status)
status = response.status

history = self.history + (
RequestHistory(method, url, error, status, redirect_location),
)

new_retry = self.new(
total=total,
connect=connect,
read=read,
redirect=redirect,
status=status_count,
other=other,
history=history,
)

if new_retry.is_exhausted():
reason = error or ResponseError(cause)
> raise MaxRetryError(_pool, url, reason) from reason # type: ignore[arg-type]
E urllib3.exceptions.MaxRetryError: HTTPSConnectionPool(host='addons.allizom.org', port=443): Max retries exceeded with url: /api/v5/addons/upload/ (Caused by NameResolutionError("<urllib3.connection.HTTPSConnection object at 0x103c5d790>: Failed to resolve 'addons.allizom.org' ([Errno 8] nodename nor servname provided, or not known)"))

venv/lib/python3.11/site-packages/urllib3/util/retry.py:519: MaxRetryError

During handling of the above exception, another exception occurred:

base_url = 'https://addons.allizom.org', session_auth = 'ldvd5ag27bkfpukx6rn2lcj0yuvakt3v', guid = 'reserved_guid@mozillaonline.com'

@pytest.mark.parametrize(
"guid",
[
"reserved_guid@mozilla.com",
"reserved_guid@mozilla.org",
"reserved_guid@pioneer.mozilla.org",
"reserved_guid@search.mozilla.org",
"reserved_guid@shield.mozilla.com",
"reserved_guid@shield.mozilla.org",
"reserved_guid@mozillaonline.com",
"reserved_guid@mozillafoundation.org",
"reserved_guid@rally.mozilla.org",
"reserved_guid@temporary-addon",
"reserved_guid@mozac.org",
],
)
@pytest.mark.serial
@pytest.mark.create_session("api_user")
def test_submit_addon_with_reserved_guid(base_url, session_auth, guid):
"""Upload an addon that has a reserved guid suffix, unavailable for regular users"""
manifest = {
**payloads.minimal_manifest,
"name": "Reserved guid",
"browser_specific_settings": {"gecko": {"id": guid}},
}
api_helpers.make_addon(manifest)
with open("sample-addons/make-addon.zip", "rb") as file:
> upload = requests.post(
url=f"{base_url}{_upload}",
headers={"Authorization": f"Session {session_auth}"},
files={"upload": file},
data={"channel": "listed"},
)

tests/api_w/test_addon_uploads.py:392:
_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _
venv/lib/python3.11/site-packages/requests/api.py:115: in post
return request("post", url, data=data, json=json, **kwargs)
venv/lib/python3.11/site-packages/requests/api.py:59: in request
return session.request(method=method, url=url, **kwargs)
venv/lib/python3.11/site-packages/requests/sessions.py:589: in request
resp = self.send(prep, **send_kwargs)
venv/lib/python3.11/site-packages/requests/sessions.py:703: in send
r = adapter.send(request, **kwargs)
_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _

self = <requests.adapters.HTTPAdapter object at 0x103c5f510>, request = <PreparedRequest [POST]>, stream = False, timeout = Timeout(connect=None, read=None, total=None), verify = True, cert = None
proxies = OrderedDict()

def send(
self, request, stream=False, timeout=None, verify=True, cert=None, proxies=None
):
"""Sends PreparedRequest object. Returns Response object.

:param request: The :class:`PreparedRequest <PreparedRequest>` being sent.
:param stream: (optional) Whether to stream the request content.
:param timeout: (optional) How long to wait for the server to send
data before giving up, as a float, or a :ref:`(connect timeout,
read timeout) <timeouts>` tuple.
:type timeout: float or tuple or urllib3 Timeout object
:param verify: (optional) Either a boolean, in which case it controls whether
we verify the server's TLS certificate, or a string, in which case it
must be a path to a CA bundle to use
:param cert: (optional) Any user-provided SSL certificate to be trusted.
:param proxies: (optional) The proxies dictionary to apply to the request.
:rtype: requests.Response
"""

try:
conn = self._get_connection(request, verify, proxies=proxies, cert=cert)
except LocationValueError as e:
raise InvalidURL(e, request=request)

self.cert_verify(conn, request.url, verify, cert)
url = self.request_url(request, proxies)
self.add_headers(
request,
stream=stream,
timeout=timeout,
verify=verify,
cert=cert,
proxies=proxies,
)

chunked = not (request.body is None or "Content-Length" in request.headers)

if isinstance(timeout, tuple):
try:
connect, read = timeout
timeout = TimeoutSauce(connect=connect, read=read)
except ValueError:
raise ValueError(
f"Invalid timeout {timeout}. Pass a (connect, read) timeout tuple, "
f"or a single float to set both timeouts to the same value."
)
elif isinstance(timeout, TimeoutSauce):
pass
else:
timeout = TimeoutSauce(connect=timeout, read=timeout)

try:
resp = conn.urlopen(
method=request.method,
url=url,
body=request.body,
headers=request.headers,
redirect=False,
assert_same_host=False,
preload_content=False,
decode_content=False,
retries=self.max_retries,
timeout=timeout,
chunked=chunked,
)

except (ProtocolError, OSError) as err:
raise ConnectionError(err, request=request)

except MaxRetryError as e:
if isinstance(e.reason, ConnectTimeoutError):
# TODO: Remove this in 3.0.0: see #2811
if not isinstance(e.reason, NewConnectionError):
raise ConnectTimeout(e, request=request)

if isinstance(e.reason, ResponseError):
raise RetryError(e, request=request)

if isinstance(e.reason, _ProxyError):
raise ProxyError(e, request=request)

if isinstance(e.reason, _SSLError):
# This branch is for urllib3 v1.22 and later.
raise SSLError(e, request=request)

> raise ConnectionError(e, request=request)
E requests.exceptions.ConnectionError: HTTPSConnectionPool(host='addons.allizom.org', port=443): Max retries exceeded with url: /api/v5/addons/upload/ (Caused by NameResolutionError("<urllib3.connection.HTTPSConnection object at 0x103c5d790>: Failed to resolve 'addons.allizom.org' ([Errno 8] nodename nor servname provided, or not known)"))

venv/lib/python3.11/site-packages/requests/adapters.py:597: ConnectionError
------------------------------Captured stdout call------------------------------
Manifest content: {'manifest_version': 2, 'version': '1.0', 'name': 'Reserved guid', 'browser_specific_settings': {'gecko': {'id': 'reserved_guid@mozillaonline.com'}}}
Failed tests/api_w/test_addon_uploads.py::test_submit_addon_with_reserved_guid[reserved_guid@mozillafoundation.org] 0.01
self = <urllib3.connection.HTTPSConnection object at 0x104121790>

def _new_conn(self) -> socket.socket:
"""Establish a socket connection and set nodelay settings on it.

:return: New socket connection.
"""
try:
> sock = connection.create_connection(
(self._dns_host, self.port),
self.timeout,
source_address=self.source_address,
socket_options=self.socket_options,
)

venv/lib/python3.11/site-packages/urllib3/connection.py:196:
_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _
venv/lib/python3.11/site-packages/urllib3/util/connection.py:60: in create_connection
for res in socket.getaddrinfo(host, port, family, socket.SOCK_STREAM):
_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _

host = 'addons.allizom.org', port = 443, family = <AddressFamily.AF_UNSPEC: 0>, type = <SocketKind.SOCK_STREAM: 1>, proto = 0, flags = 0

def getaddrinfo(host, port, family=0, type=0, proto=0, flags=0):
"""Resolve host and port into list of address info entries.

Translate the host/port argument into a sequence of 5-tuples that contain
all the necessary arguments for creating a socket connected to that service.
host is a domain name, a string representation of an IPv4/v6 address or
None. port is a string service name such as 'http', a numeric port number or
None. By passing None as the value of host and port, you can pass NULL to
the underlying C API.

The family, type and proto arguments can be optionally specified in order to
narrow the list of addresses returned. Passing zero as a value for each of
these arguments selects the full range of results.
"""
# We override this function since we want to translate the numeric family
# and socket type values to enum constants.
addrlist = []
> for res in _socket.getaddrinfo(host, port, family, type, proto, flags):
E socket.gaierror: [Errno 8] nodename nor servname provided, or not known

/Library/Frameworks/Python.framework/Versions/3.11/lib/python3.11/socket.py:962: gaierror

The above exception was the direct cause of the following exception:

self = <urllib3.connectionpool.HTTPSConnectionPool object at 0x104121390>, method = 'POST', url = '/api/v5/addons/upload/'
body = b'--77e48ae7146107b564efe2e78437814f\r\nContent-Disposition: form-data; name="channel"\r\n\r\nlisted\r\n--77e48ae71461...5\x06\x00\x00\x00\x00\x01\x00\x01\x00;\x00\x00\x00\xc4\x00\x00\x00\x00\x00\r\n--77e48ae7146107b564efe2e78437814f--\r\n'
headers = {'User-Agent': 'python-requests/2.32.0', 'Accept-Encoding': 'gzip, deflate', 'Accept': '*/*', 'Connection': 'keep-aliv...j0yuvakt3v', 'Content-Length': '523', 'Content-Type': 'multipart/form-data; boundary=77e48ae7146107b564efe2e78437814f'}
retries = Retry(total=0, connect=None, read=False, redirect=None, status=None), redirect = False, assert_same_host = False, timeout = Timeout(connect=None, read=None, total=None), pool_timeout = None
release_conn = False, chunked = False, body_pos = None, preload_content = False, decode_content = False, response_kw = {}
parsed_url = Url(scheme=None, auth=None, host=None, port=None, path='/api/v5/addons/upload/', query=None, fragment=None), destination_scheme = None, conn = None, release_this_conn = True
http_tunnel_required = False, err = None, clean_exit = False

def urlopen( # type: ignore[override]
self,
method: str,
url: str,
body: _TYPE_BODY | None = None,
headers: typing.Mapping[str, str] | None = None,
retries: Retry | bool | int | None = None,
redirect: bool = True,
assert_same_host: bool = True,
timeout: _TYPE_TIMEOUT = _DEFAULT_TIMEOUT,
pool_timeout: int | None = None,
release_conn: bool | None = None,
chunked: bool = False,
body_pos: _TYPE_BODY_POSITION | None = None,
preload_content: bool = True,
decode_content: bool = True,
**response_kw: typing.Any,
) -> BaseHTTPResponse:
"""
Get a connection from the pool and perform an HTTP request. This is the
lowest level call for making a request, so you'll need to specify all
the raw details.

.. note::

More commonly, it's appropriate to use a convenience method
such as :meth:`request`.

.. note::

`release_conn` will only behave as expected if
`preload_content=False` because we want to make
`preload_content=False` the default behaviour someday soon without
breaking backwards compatibility.

:param method:
HTTP request method (such as GET, POST, PUT, etc.)

:param url:
The URL to perform the request on.

:param body:
Data to send in the request body, either :class:`str`, :class:`bytes`,
an iterable of :class:`str`/:class:`bytes`, or a file-like object.

:param headers:
Dictionary of custom headers to send, such as User-Agent,
If-None-Match, etc. If None, pool headers are used. If provided,
these headers completely replace any pool-specific headers.

:param retries:
Configure the number of retries to allow before raising a
:class:`~urllib3.exceptions.MaxRetryError` exception.

If ``None`` (default) will retry 3 times, see ``Retry.DEFAULT``. Pass a
:class:`~urllib3.util.retry.Retry` object for fine-grained control
over different types of retries.
Pass an integer number to retry connection errors that many times,
but no other types of errors. Pass zero to never retry.

If ``False``, then retries are disabled and any exception is raised
immediately. Also, instead of raising a MaxRetryError on redirects,
the redirect response will be returned.

:type retries: :class:`~urllib3.util.retry.Retry`, False, or an int.

:param redirect:
If True, automatically handle redirects (status codes 301, 302,
303, 307, 308). Each redirect counts as a retry. Disabling retries
will disable redirect, too.

:param assert_same_host:
If ``True``, will make sure that the host of the pool requests is
consistent else will raise HostChangedError. When ``False``, you can
use the pool on an HTTP proxy and request foreign hosts.

:param timeout:
If specified, overrides the default timeout for this one
request. It may be a float (in seconds) or an instance of
:class:`urllib3.util.Timeout`.

:param pool_timeout:
If set and the pool is set to block=True, then this method will
block for ``pool_timeout`` seconds and raise EmptyPoolError if no
connection is available within the time period.

:param bool preload_content:
If True, the response's body will be preloaded into memory.

:param bool decode_content:
If True, will attempt to decode the body based on the
'content-encoding' header.

:param release_conn:
If False, then the urlopen call will not release the connection
back into the pool once a response is received (but will release if
you read the entire contents of the response such as when
`preload_content=True`). This is useful if you're not preloading
the response's content immediately. You will need to call
``r.release_conn()`` on the response ``r`` to return the connection
back into the pool. If None, it takes the value of ``preload_content``
which defaults to ``True``.

:param bool chunked:
If True, urllib3 will send the body using chunked transfer
encoding. Otherwise, urllib3 will send the body using the standard
content-length form. Defaults to False.

:param int body_pos:
Position to seek to in file-like body in the event of a retry or
redirect. Typically this won't need to be set because urllib3 will
auto-populate the value when needed.
"""
parsed_url = parse_url(url)
destination_scheme = parsed_url.scheme

if headers is None:
headers = self.headers

if not isinstance(retries, Retry):
retries = Retry.from_int(retries, redirect=redirect, default=self.retries)

if release_conn is None:
release_conn = preload_content

# Check host
if assert_same_host and not self.is_same_host(url):
raise HostChangedError(self, url, retries)

# Ensure that the URL we're connecting to is properly encoded
if url.startswith("/"):
url = to_str(_encode_target(url))
else:
url = to_str(parsed_url.url)

conn = None

# Track whether `conn` needs to be released before
# returning/raising/recursing. Update this variable if necessary, and
# leave `release_conn` constant throughout the function. That way, if
# the function recurses, the original value of `release_conn` will be
# passed down into the recursive call, and its value will be respected.
#
# See issue #651 [1] for details.
#
# [1] <https://github.com/urllib3/urllib3/issues/651>
release_this_conn = release_conn

http_tunnel_required = connection_requires_http_tunnel(
self.proxy, self.proxy_config, destination_scheme
)

# Merge the proxy headers. Only done when not using HTTP CONNECT. We
# have to copy the headers dict so we can safely change it without those
# changes being reflected in anyone else's copy.
if not http_tunnel_required:
headers = headers.copy() # type: ignore[attr-defined]
headers.update(self.proxy_headers) # type: ignore[union-attr]

# Must keep the exception bound to a separate variable or else Python 3
# complains about UnboundLocalError.
err = None

# Keep track of whether we cleanly exited the except block. This
# ensures we do proper cleanup in finally.
clean_exit = False

# Rewind body position, if needed. Record current position
# for future rewinds in the event of a redirect/retry.
body_pos = set_file_position(body, body_pos)

try:
# Request a connection from the queue.
timeout_obj = self._get_timeout(timeout)
conn = self._get_conn(timeout=pool_timeout)

conn.timeout = timeout_obj.connect_timeout # type: ignore[assignment]

# Is this a closed/new connection that requires CONNECT tunnelling?
if self.proxy is not None and http_tunnel_required and conn.is_closed:
try:
self._prepare_proxy(conn)
except (BaseSSLError, OSError, SocketTimeout) as e:
self._raise_timeout(
err=e, url=self.proxy.url, timeout_value=conn.timeout
)
raise

# If we're going to release the connection in ``finally:``, then
# the response doesn't need to know about the connection. Otherwise
# it will also try to release it and we'll have a double-release
# mess.
response_conn = conn if not release_conn else None

# Make the request on the HTTPConnection object
> response = self._make_request(
conn,
method,
url,
timeout=timeout_obj,
body=body,
headers=headers,
chunked=chunked,
retries=retries,
response_conn=response_conn,
preload_content=preload_content,
decode_content=decode_content,
**response_kw,
)

venv/lib/python3.11/site-packages/urllib3/connectionpool.py:789:
_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _
venv/lib/python3.11/site-packages/urllib3/connectionpool.py:490: in _make_request
raise new_e
venv/lib/python3.11/site-packages/urllib3/connectionpool.py:466: in _make_request
self._validate_conn(conn)
venv/lib/python3.11/site-packages/urllib3/connectionpool.py:1095: in _validate_conn
conn.connect()
venv/lib/python3.11/site-packages/urllib3/connection.py:615: in connect
self.sock = sock = self._new_conn()
_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _

self = <urllib3.connection.HTTPSConnection object at 0x104121790>

def _new_conn(self) -> socket.socket:
"""Establish a socket connection and set nodelay settings on it.

:return: New socket connection.
"""
try:
sock = connection.create_connection(
(self._dns_host, self.port),
self.timeout,
source_address=self.source_address,
socket_options=self.socket_options,
)
except socket.gaierror as e:
> raise NameResolutionError(self.host, self, e) from e
E urllib3.exceptions.NameResolutionError: <urllib3.connection.HTTPSConnection object at 0x104121790>: Failed to resolve 'addons.allizom.org' ([Errno 8] nodename nor servname provided, or not known)

venv/lib/python3.11/site-packages/urllib3/connection.py:203: NameResolutionError

The above exception was the direct cause of the following exception:

self = <requests.adapters.HTTPAdapter object at 0x1041237d0>, request = <PreparedRequest [POST]>, stream = False, timeout = Timeout(connect=None, read=None, total=None), verify = True, cert = None
proxies = OrderedDict()

def send(
self, request, stream=False, timeout=None, verify=True, cert=None, proxies=None
):
"""Sends PreparedRequest object. Returns Response object.

:param request: The :class:`PreparedRequest <PreparedRequest>` being sent.
:param stream: (optional) Whether to stream the request content.
:param timeout: (optional) How long to wait for the server to send
data before giving up, as a float, or a :ref:`(connect timeout,
read timeout) <timeouts>` tuple.
:type timeout: float or tuple or urllib3 Timeout object
:param verify: (optional) Either a boolean, in which case it controls whether
we verify the server's TLS certificate, or a string, in which case it
must be a path to a CA bundle to use
:param cert: (optional) Any user-provided SSL certificate to be trusted.
:param proxies: (optional) The proxies dictionary to apply to the request.
:rtype: requests.Response
"""

try:
conn = self._get_connection(request, verify, proxies=proxies, cert=cert)
except LocationValueError as e:
raise InvalidURL(e, request=request)

self.cert_verify(conn, request.url, verify, cert)
url = self.request_url(request, proxies)
self.add_headers(
request,
stream=stream,
timeout=timeout,
verify=verify,
cert=cert,
proxies=proxies,
)

chunked = not (request.body is None or "Content-Length" in request.headers)

if isinstance(timeout, tuple):
try:
connect, read = timeout
timeout = TimeoutSauce(connect=connect, read=read)
except ValueError:
raise ValueError(
f"Invalid timeout {timeout}. Pass a (connect, read) timeout tuple, "
f"or a single float to set both timeouts to the same value."
)
elif isinstance(timeout, TimeoutSauce):
pass
else:
timeout = TimeoutSauce(connect=timeout, read=timeout)

try:
> resp = conn.urlopen(
method=request.method,
url=url,
body=request.body,
headers=request.headers,
redirect=False,
assert_same_host=False,
preload_content=False,
decode_content=False,
retries=self.max_retries,
timeout=timeout,
chunked=chunked,
)

venv/lib/python3.11/site-packages/requests/adapters.py:564:
_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _
venv/lib/python3.11/site-packages/urllib3/connectionpool.py:843: in urlopen
retries = retries.increment(
_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _

self = Retry(total=0, connect=None, read=False, redirect=None, status=None), method = 'POST', url = '/api/v5/addons/upload/', response = None
error = NameResolutionError("<urllib3.connection.HTTPSConnection object at 0x104121790>: Failed to resolve 'addons.allizom.org' ([Errno 8] nodename nor servname provided, or not known)")
_pool = <urllib3.connectionpool.HTTPSConnectionPool object at 0x104121390>, _stacktrace = <traceback object at 0x1041217c0>

def increment(
self,
method: str | None = None,
url: str | None = None,
response: BaseHTTPResponse | None = None,
error: Exception | None = None,
_pool: ConnectionPool | None = None,
_stacktrace: TracebackType | None = None,
) -> Self:
"""Return a new Retry object with incremented retry counters.

:param response: A response object, or None, if the server did not
return a response.
:type response: :class:`~urllib3.response.BaseHTTPResponse`
:param Exception error: An error encountered during the request, or
None if the response was received successfully.

:return: A new ``Retry`` object.
"""
if self.total is False and error:
# Disabled, indicate to re-raise the error.
raise reraise(type(error), error, _stacktrace)

total = self.total
if total is not None:
total -= 1

connect = self.connect
read = self.read
redirect = self.redirect
status_count = self.status
other = self.other
cause = "unknown"
status = None
redirect_location = None

if error and self._is_connection_error(error):
# Connect retry?
if connect is False:
raise reraise(type(error), error, _stacktrace)
elif connect is not None:
connect -= 1

elif error and self._is_read_error(error):
# Read retry?
if read is False or method is None or not self._is_method_retryable(method):
raise reraise(type(error), error, _stacktrace)
elif read is not None:
read -= 1

elif error:
# Other retry?
if other is not None:
other -= 1

elif response and response.get_redirect_location():
# Redirect retry?
if redirect is not None:
redirect -= 1
cause = "too many redirects"
response_redirect_location = response.get_redirect_location()
if response_redirect_location:
redirect_location = response_redirect_location
status = response.status

else:
# Incrementing because of a server error like a 500 in
# status_forcelist and the given method is in the allowed_methods
cause = ResponseError.GENERIC_ERROR
if response and response.status:
if status_count is not None:
status_count -= 1
cause = ResponseError.SPECIFIC_ERROR.format(status_code=response.status)
status = response.status

history = self.history + (
RequestHistory(method, url, error, status, redirect_location),
)

new_retry = self.new(
total=total,
connect=connect,
read=read,
redirect=redirect,
status=status_count,
other=other,
history=history,
)

if new_retry.is_exhausted():
reason = error or ResponseError(cause)
> raise MaxRetryError(_pool, url, reason) from reason # type: ignore[arg-type]
E urllib3.exceptions.MaxRetryError: HTTPSConnectionPool(host='addons.allizom.org', port=443): Max retries exceeded with url: /api/v5/addons/upload/ (Caused by NameResolutionError("<urllib3.connection.HTTPSConnection object at 0x104121790>: Failed to resolve 'addons.allizom.org' ([Errno 8] nodename nor servname provided, or not known)"))

venv/lib/python3.11/site-packages/urllib3/util/retry.py:519: MaxRetryError

During handling of the above exception, another exception occurred:

base_url = 'https://addons.allizom.org', session_auth = 'ldvd5ag27bkfpukx6rn2lcj0yuvakt3v', guid = 'reserved_guid@mozillafoundation.org'

@pytest.mark.parametrize(
"guid",
[
"reserved_guid@mozilla.com",
"reserved_guid@mozilla.org",
"reserved_guid@pioneer.mozilla.org",
"reserved_guid@search.mozilla.org",
"reserved_guid@shield.mozilla.com",
"reserved_guid@shield.mozilla.org",
"reserved_guid@mozillaonline.com",
"reserved_guid@mozillafoundation.org",
"reserved_guid@rally.mozilla.org",
"reserved_guid@temporary-addon",
"reserved_guid@mozac.org",
],
)
@pytest.mark.serial
@pytest.mark.create_session("api_user")
def test_submit_addon_with_reserved_guid(base_url, session_auth, guid):
"""Upload an addon that has a reserved guid suffix, unavailable for regular users"""
manifest = {
**payloads.minimal_manifest,
"name": "Reserved guid",
"browser_specific_settings": {"gecko": {"id": guid}},
}
api_helpers.make_addon(manifest)
with open("sample-addons/make-addon.zip", "rb") as file:
> upload = requests.post(
url=f"{base_url}{_upload}",
headers={"Authorization": f"Session {session_auth}"},
files={"upload": file},
data={"channel": "listed"},
)

tests/api_w/test_addon_uploads.py:392:
_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _
venv/lib/python3.11/site-packages/requests/api.py:115: in post
return request("post", url, data=data, json=json, **kwargs)
venv/lib/python3.11/site-packages/requests/api.py:59: in request
return session.request(method=method, url=url, **kwargs)
venv/lib/python3.11/site-packages/requests/sessions.py:589: in request
resp = self.send(prep, **send_kwargs)
venv/lib/python3.11/site-packages/requests/sessions.py:703: in send
r = adapter.send(request, **kwargs)
_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _

self = <requests.adapters.HTTPAdapter object at 0x1041237d0>, request = <PreparedRequest [POST]>, stream = False, timeout = Timeout(connect=None, read=None, total=None), verify = True, cert = None
proxies = OrderedDict()

def send(
self, request, stream=False, timeout=None, verify=True, cert=None, proxies=None
):
"""Sends PreparedRequest object. Returns Response object.

:param request: The :class:`PreparedRequest <PreparedRequest>` being sent.
:param stream: (optional) Whether to stream the request content.
:param timeout: (optional) How long to wait for the server to send
data before giving up, as a float, or a :ref:`(connect timeout,
read timeout) <timeouts>` tuple.
:type timeout: float or tuple or urllib3 Timeout object
:param verify: (optional) Either a boolean, in which case it controls whether
we verify the server's TLS certificate, or a string, in which case it
must be a path to a CA bundle to use
:param cert: (optional) Any user-provided SSL certificate to be trusted.
:param proxies: (optional) The proxies dictionary to apply to the request.
:rtype: requests.Response
"""

try:
conn = self._get_connection(request, verify, proxies=proxies, cert=cert)
except LocationValueError as e:
raise InvalidURL(e, request=request)

self.cert_verify(conn, request.url, verify, cert)
url = self.request_url(request, proxies)
self.add_headers(
request,
stream=stream,
timeout=timeout,
verify=verify,
cert=cert,
proxies=proxies,
)

chunked = not (request.body is None or "Content-Length" in request.headers)

if isinstance(timeout, tuple):
try:
connect, read = timeout
timeout = TimeoutSauce(connect=connect, read=read)
except ValueError:
raise ValueError(
f"Invalid timeout {timeout}. Pass a (connect, read) timeout tuple, "
f"or a single float to set both timeouts to the same value."
)
elif isinstance(timeout, TimeoutSauce):
pass
else:
timeout = TimeoutSauce(connect=timeout, read=timeout)

try:
resp = conn.urlopen(
method=request.method,
url=url,
body=request.body,
headers=request.headers,
redirect=False,
assert_same_host=False,
preload_content=False,
decode_content=False,
retries=self.max_retries,
timeout=timeout,
chunked=chunked,
)

except (ProtocolError, OSError) as err:
raise ConnectionError(err, request=request)

except MaxRetryError as e:
if isinstance(e.reason, ConnectTimeoutError):
# TODO: Remove this in 3.0.0: see #2811
if not isinstance(e.reason, NewConnectionError):
raise ConnectTimeout(e, request=request)

if isinstance(e.reason, ResponseError):
raise RetryError(e, request=request)

if isinstance(e.reason, _ProxyError):
raise ProxyError(e, request=request)

if isinstance(e.reason, _SSLError):
# This branch is for urllib3 v1.22 and later.
raise SSLError(e, request=request)

> raise ConnectionError(e, request=request)
E requests.exceptions.ConnectionError: HTTPSConnectionPool(host='addons.allizom.org', port=443): Max retries exceeded with url: /api/v5/addons/upload/ (Caused by NameResolutionError("<urllib3.connection.HTTPSConnection object at 0x104121790>: Failed to resolve 'addons.allizom.org' ([Errno 8] nodename nor servname provided, or not known)"))

venv/lib/python3.11/site-packages/requests/adapters.py:597: ConnectionError
------------------------------Captured stdout call------------------------------
Manifest content: {'manifest_version': 2, 'version': '1.0', 'name': 'Reserved guid', 'browser_specific_settings': {'gecko': {'id': 'reserved_guid@mozillafoundation.org'}}}
Failed tests/api_w/test_addon_uploads.py::test_submit_addon_with_reserved_guid[reserved_guid@rally.mozilla.org] 0.07
self = <urllib3.connection.HTTPSConnection object at 0x104146310>

def _new_conn(self) -> socket.socket:
"""Establish a socket connection and set nodelay settings on it.

:return: New socket connection.
"""
try:
> sock = connection.create_connection(
(self._dns_host, self.port),
self.timeout,
source_address=self.source_address,
socket_options=self.socket_options,
)

venv/lib/python3.11/site-packages/urllib3/connection.py:196:
_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _
venv/lib/python3.11/site-packages/urllib3/util/connection.py:60: in create_connection
for res in socket.getaddrinfo(host, port, family, socket.SOCK_STREAM):
_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _

host = 'addons.allizom.org', port = 443, family = <AddressFamily.AF_UNSPEC: 0>, type = <SocketKind.SOCK_STREAM: 1>, proto = 0, flags = 0

def getaddrinfo(host, port, family=0, type=0, proto=0, flags=0):
"""Resolve host and port into list of address info entries.

Translate the host/port argument into a sequence of 5-tuples that contain
all the necessary arguments for creating a socket connected to that service.
host is a domain name, a string representation of an IPv4/v6 address or
None. port is a string service name such as 'http', a numeric port number or
None. By passing None as the value of host and port, you can pass NULL to
the underlying C API.

The family, type and proto arguments can be optionally specified in order to
narrow the list of addresses returned. Passing zero as a value for each of
these arguments selects the full range of results.
"""
# We override this function since we want to translate the numeric family
# and socket type values to enum constants.
addrlist = []
> for res in _socket.getaddrinfo(host, port, family, type, proto, flags):
E socket.gaierror: [Errno 8] nodename nor servname provided, or not known

/Library/Frameworks/Python.framework/Versions/3.11/lib/python3.11/socket.py:962: gaierror

The above exception was the direct cause of the following exception:

self = <urllib3.connectionpool.HTTPSConnectionPool object at 0x104146710>, method = 'POST', url = '/api/v5/addons/upload/'
body = b'--89747beb5350f43a9d12329b797c8477\r\nContent-Disposition: form-data; name="channel"\r\n\r\nlisted\r\n--89747beb5350...5\x06\x00\x00\x00\x00\x01\x00\x01\x00;\x00\x00\x00\xc0\x00\x00\x00\x00\x00\r\n--89747beb5350f43a9d12329b797c8477--\r\n'
headers = {'User-Agent': 'python-requests/2.32.0', 'Accept-Encoding': 'gzip, deflate', 'Accept': '*/*', 'Connection': 'keep-aliv...j0yuvakt3v', 'Content-Length': '519', 'Content-Type': 'multipart/form-data; boundary=89747beb5350f43a9d12329b797c8477'}
retries = Retry(total=0, connect=None, read=False, redirect=None, status=None), redirect = False, assert_same_host = False, timeout = Timeout(connect=None, read=None, total=None), pool_timeout = None
release_conn = False, chunked = False, body_pos = None, preload_content = False, decode_content = False, response_kw = {}
parsed_url = Url(scheme=None, auth=None, host=None, port=None, path='/api/v5/addons/upload/', query=None, fragment=None), destination_scheme = None, conn = None, release_this_conn = True
http_tunnel_required = False, err = None, clean_exit = False

def urlopen( # type: ignore[override]
self,
method: str,
url: str,
body: _TYPE_BODY | None = None,
headers: typing.Mapping[str, str] | None = None,
retries: Retry | bool | int | None = None,
redirect: bool = True,
assert_same_host: bool = True,
timeout: _TYPE_TIMEOUT = _DEFAULT_TIMEOUT,
pool_timeout: int | None = None,
release_conn: bool | None = None,
chunked: bool = False,
body_pos: _TYPE_BODY_POSITION | None = None,
preload_content: bool = True,
decode_content: bool = True,
**response_kw: typing.Any,
) -> BaseHTTPResponse:
"""
Get a connection from the pool and perform an HTTP request. This is the
lowest level call for making a request, so you'll need to specify all
the raw details.

.. note::

More commonly, it's appropriate to use a convenience method
such as :meth:`request`.

.. note::

`release_conn` will only behave as expected if
`preload_content=False` because we want to make
`preload_content=False` the default behaviour someday soon without
breaking backwards compatibility.

:param method:
HTTP request method (such as GET, POST, PUT, etc.)

:param url:
The URL to perform the request on.

:param body:
Data to send in the request body, either :class:`str`, :class:`bytes`,
an iterable of :class:`str`/:class:`bytes`, or a file-like object.

:param headers:
Dictionary of custom headers to send, such as User-Agent,
If-None-Match, etc. If None, pool headers are used. If provided,
these headers completely replace any pool-specific headers.

:param retries:
Configure the number of retries to allow before raising a
:class:`~urllib3.exceptions.MaxRetryError` exception.

If ``None`` (default) will retry 3 times, see ``Retry.DEFAULT``. Pass a
:class:`~urllib3.util.retry.Retry` object for fine-grained control
over different types of retries.
Pass an integer number to retry connection errors that many times,
but no other types of errors. Pass zero to never retry.

If ``False``, then retries are disabled and any exception is raised
immediately. Also, instead of raising a MaxRetryError on redirects,
the redirect response will be returned.

:type retries: :class:`~urllib3.util.retry.Retry`, False, or an int.

:param redirect:
If True, automatically handle redirects (status codes 301, 302,
303, 307, 308). Each redirect counts as a retry. Disabling retries
will disable redirect, too.

:param assert_same_host:
If ``True``, will make sure that the host of the pool requests is
consistent else will raise HostChangedError. When ``False``, you can
use the pool on an HTTP proxy and request foreign hosts.

:param timeout:
If specified, overrides the default timeout for this one
request. It may be a float (in seconds) or an instance of
:class:`urllib3.util.Timeout`.

:param pool_timeout:
If set and the pool is set to block=True, then this method will
block for ``pool_timeout`` seconds and raise EmptyPoolError if no
connection is available within the time period.

:param bool preload_content:
If True, the response's body will be preloaded into memory.

:param bool decode_content:
If True, will attempt to decode the body based on the
'content-encoding' header.

:param release_conn:
If False, then the urlopen call will not release the connection
back into the pool once a response is received (but will release if
you read the entire contents of the response such as when
`preload_content=True`). This is useful if you're not preloading
the response's content immediately. You will need to call
``r.release_conn()`` on the response ``r`` to return the connection
back into the pool. If None, it takes the value of ``preload_content``
which defaults to ``True``.

:param bool chunked:
If True, urllib3 will send the body using chunked transfer
encoding. Otherwise, urllib3 will send the body using the standard
content-length form. Defaults to False.

:param int body_pos:
Position to seek to in file-like body in the event of a retry or
redirect. Typically this won't need to be set because urllib3 will
auto-populate the value when needed.
"""
parsed_url = parse_url(url)
destination_scheme = parsed_url.scheme

if headers is None:
headers = self.headers

if not isinstance(retries, Retry):
retries = Retry.from_int(retries, redirect=redirect, default=self.retries)

if release_conn is None:
release_conn = preload_content

# Check host
if assert_same_host and not self.is_same_host(url):
raise HostChangedError(self, url, retries)

# Ensure that the URL we're connecting to is properly encoded
if url.startswith("/"):
url = to_str(_encode_target(url))
else:
url = to_str(parsed_url.url)

conn = None

# Track whether `conn` needs to be released before
# returning/raising/recursing. Update this variable if necessary, and
# leave `release_conn` constant throughout the function. That way, if
# the function recurses, the original value of `release_conn` will be
# passed down into the recursive call, and its value will be respected.
#
# See issue #651 [1] for details.
#
# [1] <https://github.com/urllib3/urllib3/issues/651>
release_this_conn = release_conn

http_tunnel_required = connection_requires_http_tunnel(
self.proxy, self.proxy_config, destination_scheme
)

# Merge the proxy headers. Only done when not using HTTP CONNECT. We
# have to copy the headers dict so we can safely change it without those
# changes being reflected in anyone else's copy.
if not http_tunnel_required:
headers = headers.copy() # type: ignore[attr-defined]
headers.update(self.proxy_headers) # type: ignore[union-attr]

# Must keep the exception bound to a separate variable or else Python 3
# complains about UnboundLocalError.
err = None

# Keep track of whether we cleanly exited the except block. This
# ensures we do proper cleanup in finally.
clean_exit = False

# Rewind body position, if needed. Record current position
# for future rewinds in the event of a redirect/retry.
body_pos = set_file_position(body, body_pos)

try:
# Request a connection from the queue.
timeout_obj = self._get_timeout(timeout)
conn = self._get_conn(timeout=pool_timeout)

conn.timeout = timeout_obj.connect_timeout # type: ignore[assignment]

# Is this a closed/new connection that requires CONNECT tunnelling?
if self.proxy is not None and http_tunnel_required and conn.is_closed:
try:
self._prepare_proxy(conn)
except (BaseSSLError, OSError, SocketTimeout) as e:
self._raise_timeout(
err=e, url=self.proxy.url, timeout_value=conn.timeout
)
raise

# If we're going to release the connection in ``finally:``, then
# the response doesn't need to know about the connection. Otherwise
# it will also try to release it and we'll have a double-release
# mess.
response_conn = conn if not release_conn else None

# Make the request on the HTTPConnection object
> response = self._make_request(
conn,
method,
url,
timeout=timeout_obj,
body=body,
headers=headers,
chunked=chunked,
retries=retries,
response_conn=response_conn,
preload_content=preload_content,
decode_content=decode_content,
**response_kw,
)

venv/lib/python3.11/site-packages/urllib3/connectionpool.py:789:
_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _
venv/lib/python3.11/site-packages/urllib3/connectionpool.py:490: in _make_request
raise new_e
venv/lib/python3.11/site-packages/urllib3/connectionpool.py:466: in _make_request
self._validate_conn(conn)
venv/lib/python3.11/site-packages/urllib3/connectionpool.py:1095: in _validate_conn
conn.connect()
venv/lib/python3.11/site-packages/urllib3/connection.py:615: in connect
self.sock = sock = self._new_conn()
_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _

self = <urllib3.connection.HTTPSConnection object at 0x104146310>

def _new_conn(self) -> socket.socket:
"""Establish a socket connection and set nodelay settings on it.

:return: New socket connection.
"""
try:
sock = connection.create_connection(
(self._dns_host, self.port),
self.timeout,
source_address=self.source_address,
socket_options=self.socket_options,
)
except socket.gaierror as e:
> raise NameResolutionError(self.host, self, e) from e
E urllib3.exceptions.NameResolutionError: <urllib3.connection.HTTPSConnection object at 0x104146310>: Failed to resolve 'addons.allizom.org' ([Errno 8] nodename nor servname provided, or not known)

venv/lib/python3.11/site-packages/urllib3/connection.py:203: NameResolutionError

The above exception was the direct cause of the following exception:

self = <requests.adapters.HTTPAdapter object at 0x104146ed0>, request = <PreparedRequest [POST]>, stream = False, timeout = Timeout(connect=None, read=None, total=None), verify = True, cert = None
proxies = OrderedDict()

def send(
self, request, stream=False, timeout=None, verify=True, cert=None, proxies=None
):
"""Sends PreparedRequest object. Returns Response object.

:param request: The :class:`PreparedRequest <PreparedRequest>` being sent.
:param stream: (optional) Whether to stream the request content.
:param timeout: (optional) How long to wait for the server to send
data before giving up, as a float, or a :ref:`(connect timeout,
read timeout) <timeouts>` tuple.
:type timeout: float or tuple or urllib3 Timeout object
:param verify: (optional) Either a boolean, in which case it controls whether
we verify the server's TLS certificate, or a string, in which case it
must be a path to a CA bundle to use
:param cert: (optional) Any user-provided SSL certificate to be trusted.
:param proxies: (optional) The proxies dictionary to apply to the request.
:rtype: requests.Response
"""

try:
conn = self._get_connection(request, verify, proxies=proxies, cert=cert)
except LocationValueError as e:
raise InvalidURL(e, request=request)

self.cert_verify(conn, request.url, verify, cert)
url = self.request_url(request, proxies)
self.add_headers(
request,
stream=stream,
timeout=timeout,
verify=verify,
cert=cert,
proxies=proxies,
)

chunked = not (request.body is None or "Content-Length" in request.headers)

if isinstance(timeout, tuple):
try:
connect, read = timeout
timeout = TimeoutSauce(connect=connect, read=read)
except ValueError:
raise ValueError(
f"Invalid timeout {timeout}. Pass a (connect, read) timeout tuple, "
f"or a single float to set both timeouts to the same value."
)
elif isinstance(timeout, TimeoutSauce):
pass
else:
timeout = TimeoutSauce(connect=timeout, read=timeout)

try:
> resp = conn.urlopen(
method=request.method,
url=url,
body=request.body,
headers=request.headers,
redirect=False,
assert_same_host=False,
preload_content=False,
decode_content=False,
retries=self.max_retries,
timeout=timeout,
chunked=chunked,
)

venv/lib/python3.11/site-packages/requests/adapters.py:564:
_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _
venv/lib/python3.11/site-packages/urllib3/connectionpool.py:843: in urlopen
retries = retries.increment(
_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _

self = Retry(total=0, connect=None, read=False, redirect=None, status=None), method = 'POST', url = '/api/v5/addons/upload/', response = None
error = NameResolutionError("<urllib3.connection.HTTPSConnection object at 0x104146310>: Failed to resolve 'addons.allizom.org' ([Errno 8] nodename nor servname provided, or not known)")
_pool = <urllib3.connectionpool.HTTPSConnectionPool object at 0x104146710>, _stacktrace = <traceback object at 0x104145cc0>

def increment(
self,
method: str | None = None,
url: str | None = None,
response: BaseHTTPResponse | None = None,
error: Exception | None = None,
_pool: ConnectionPool | None = None,
_stacktrace: TracebackType | None = None,
) -> Self:
"""Return a new Retry object with incremented retry counters.

:param response: A response object, or None, if the server did not
return a response.
:type response: :class:`~urllib3.response.BaseHTTPResponse`
:param Exception error: An error encountered during the request, or
None if the response was received successfully.

:return: A new ``Retry`` object.
"""
if self.total is False and error:
# Disabled, indicate to re-raise the error.
raise reraise(type(error), error, _stacktrace)

total = self.total
if total is not None:
total -= 1

connect = self.connect
read = self.read
redirect = self.redirect
status_count = self.status
other = self.other
cause = "unknown"
status = None
redirect_location = None

if error and self._is_connection_error(error):
# Connect retry?
if connect is False:
raise reraise(type(error), error, _stacktrace)
elif connect is not None:
connect -= 1

elif error and self._is_read_error(error):
# Read retry?
if read is False or method is None or not self._is_method_retryable(method):
raise reraise(type(error), error, _stacktrace)
elif read is not None:
read -= 1

elif error:
# Other retry?
if other is not None:
other -= 1

elif response and response.get_redirect_location():
# Redirect retry?
if redirect is not None:
redirect -= 1
cause = "too many redirects"
response_redirect_location = response.get_redirect_location()
if response_redirect_location:
redirect_location = response_redirect_location
status = response.status

else:
# Incrementing because of a server error like a 500 in
# status_forcelist and the given method is in the allowed_methods
cause = ResponseError.GENERIC_ERROR
if response and response.status:
if status_count is not None:
status_count -= 1
cause = ResponseError.SPECIFIC_ERROR.format(status_code=response.status)
status = response.status

history = self.history + (
RequestHistory(method, url, error, status, redirect_location),
)

new_retry = self.new(
total=total,
connect=connect,
read=read,
redirect=redirect,
status=status_count,
other=other,
history=history,
)

if new_retry.is_exhausted():
reason = error or ResponseError(cause)
> raise MaxRetryError(_pool, url, reason) from reason # type: ignore[arg-type]
E urllib3.exceptions.MaxRetryError: HTTPSConnectionPool(host='addons.allizom.org', port=443): Max retries exceeded with url: /api/v5/addons/upload/ (Caused by NameResolutionError("<urllib3.connection.HTTPSConnection object at 0x104146310>: Failed to resolve 'addons.allizom.org' ([Errno 8] nodename nor servname provided, or not known)"))

venv/lib/python3.11/site-packages/urllib3/util/retry.py:519: MaxRetryError

During handling of the above exception, another exception occurred:

base_url = 'https://addons.allizom.org', session_auth = 'ldvd5ag27bkfpukx6rn2lcj0yuvakt3v', guid = 'reserved_guid@rally.mozilla.org'

@pytest.mark.parametrize(
"guid",
[
"reserved_guid@mozilla.com",
"reserved_guid@mozilla.org",
"reserved_guid@pioneer.mozilla.org",
"reserved_guid@search.mozilla.org",
"reserved_guid@shield.mozilla.com",
"reserved_guid@shield.mozilla.org",
"reserved_guid@mozillaonline.com",
"reserved_guid@mozillafoundation.org",
"reserved_guid@rally.mozilla.org",
"reserved_guid@temporary-addon",
"reserved_guid@mozac.org",
],
)
@pytest.mark.serial
@pytest.mark.create_session("api_user")
def test_submit_addon_with_reserved_guid(base_url, session_auth, guid):
"""Upload an addon that has a reserved guid suffix, unavailable for regular users"""
manifest = {
**payloads.minimal_manifest,
"name": "Reserved guid",
"browser_specific_settings": {"gecko": {"id": guid}},
}
api_helpers.make_addon(manifest)
with open("sample-addons/make-addon.zip", "rb") as file:
> upload = requests.post(
url=f"{base_url}{_upload}",
headers={"Authorization": f"Session {session_auth}"},
files={"upload": file},
data={"channel": "listed"},
)

tests/api_w/test_addon_uploads.py:392:
_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _
venv/lib/python3.11/site-packages/requests/api.py:115: in post
return request("post", url, data=data, json=json, **kwargs)
venv/lib/python3.11/site-packages/requests/api.py:59: in request
return session.request(method=method, url=url, **kwargs)
venv/lib/python3.11/site-packages/requests/sessions.py:589: in request
resp = self.send(prep, **send_kwargs)
venv/lib/python3.11/site-packages/requests/sessions.py:703: in send
r = adapter.send(request, **kwargs)
_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _

self = <requests.adapters.HTTPAdapter object at 0x104146ed0>, request = <PreparedRequest [POST]>, stream = False, timeout = Timeout(connect=None, read=None, total=None), verify = True, cert = None
proxies = OrderedDict()

def send(
self, request, stream=False, timeout=None, verify=True, cert=None, proxies=None
):
"""Sends PreparedRequest object. Returns Response object.

:param request: The :class:`PreparedRequest <PreparedRequest>` being sent.
:param stream: (optional) Whether to stream the request content.
:param timeout: (optional) How long to wait for the server to send
data before giving up, as a float, or a :ref:`(connect timeout,
read timeout) <timeouts>` tuple.
:type timeout: float or tuple or urllib3 Timeout object
:param verify: (optional) Either a boolean, in which case it controls whether
we verify the server's TLS certificate, or a string, in which case it
must be a path to a CA bundle to use
:param cert: (optional) Any user-provided SSL certificate to be trusted.
:param proxies: (optional) The proxies dictionary to apply to the request.
:rtype: requests.Response
"""

try:
conn = self._get_connection(request, verify, proxies=proxies, cert=cert)
except LocationValueError as e:
raise InvalidURL(e, request=request)

self.cert_verify(conn, request.url, verify, cert)
url = self.request_url(request, proxies)
self.add_headers(
request,
stream=stream,
timeout=timeout,
verify=verify,
cert=cert,
proxies=proxies,
)

chunked = not (request.body is None or "Content-Length" in request.headers)

if isinstance(timeout, tuple):
try:
connect, read = timeout
timeout = TimeoutSauce(connect=connect, read=read)
except ValueError:
raise ValueError(
f"Invalid timeout {timeout}. Pass a (connect, read) timeout tuple, "
f"or a single float to set both timeouts to the same value."
)
elif isinstance(timeout, TimeoutSauce):
pass
else:
timeout = TimeoutSauce(connect=timeout, read=timeout)

try:
resp = conn.urlopen(
method=request.method,
url=url,
body=request.body,
headers=request.headers,
redirect=False,
assert_same_host=False,
preload_content=False,
decode_content=False,
retries=self.max_retries,
timeout=timeout,
chunked=chunked,
)

except (ProtocolError, OSError) as err:
raise ConnectionError(err, request=request)

except MaxRetryError as e:
if isinstance(e.reason, ConnectTimeoutError):
# TODO: Remove this in 3.0.0: see #2811
if not isinstance(e.reason, NewConnectionError):
raise ConnectTimeout(e, request=request)

if isinstance(e.reason, ResponseError):
raise RetryError(e, request=request)

if isinstance(e.reason, _ProxyError):
raise ProxyError(e, request=request)

if isinstance(e.reason, _SSLError):
# This branch is for urllib3 v1.22 and later.
raise SSLError(e, request=request)

> raise ConnectionError(e, request=request)
E requests.exceptions.ConnectionError: HTTPSConnectionPool(host='addons.allizom.org', port=443): Max retries exceeded with url: /api/v5/addons/upload/ (Caused by NameResolutionError("<urllib3.connection.HTTPSConnection object at 0x104146310>: Failed to resolve 'addons.allizom.org' ([Errno 8] nodename nor servname provided, or not known)"))

venv/lib/python3.11/site-packages/requests/adapters.py:597: ConnectionError
------------------------------Captured stdout call------------------------------
Manifest content: {'manifest_version': 2, 'version': '1.0', 'name': 'Reserved guid', 'browser_specific_settings': {'gecko': {'id': 'reserved_guid@rally.mozilla.org'}}}
Failed tests/api_w/test_addon_uploads.py::test_submit_addon_with_reserved_guid[reserved_guid@temporary-addon] 0.02
self = <urllib3.connection.HTTPSConnection object at 0x104099c50>

def _new_conn(self) -> socket.socket:
"""Establish a socket connection and set nodelay settings on it.

:return: New socket connection.
"""
try:
> sock = connection.create_connection(
(self._dns_host, self.port),
self.timeout,
source_address=self.source_address,
socket_options=self.socket_options,
)

venv/lib/python3.11/site-packages/urllib3/connection.py:196:
_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _
venv/lib/python3.11/site-packages/urllib3/util/connection.py:60: in create_connection
for res in socket.getaddrinfo(host, port, family, socket.SOCK_STREAM):
_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _

host = 'addons.allizom.org', port = 443, family = <AddressFamily.AF_UNSPEC: 0>, type = <SocketKind.SOCK_STREAM: 1>, proto = 0, flags = 0

def getaddrinfo(host, port, family=0, type=0, proto=0, flags=0):
"""Resolve host and port into list of address info entries.

Translate the host/port argument into a sequence of 5-tuples that contain
all the necessary arguments for creating a socket connected to that service.
host is a domain name, a string representation of an IPv4/v6 address or
None. port is a string service name such as 'http', a numeric port number or
None. By passing None as the value of host and port, you can pass NULL to
the underlying C API.

The family, type and proto arguments can be optionally specified in order to
narrow the list of addresses returned. Passing zero as a value for each of
these arguments selects the full range of results.
"""
# We override this function since we want to translate the numeric family
# and socket type values to enum constants.
addrlist = []
> for res in _socket.getaddrinfo(host, port, family, type, proto, flags):
E socket.gaierror: [Errno 8] nodename nor servname provided, or not known

/Library/Frameworks/Python.framework/Versions/3.11/lib/python3.11/socket.py:962: gaierror

The above exception was the direct cause of the following exception:

self = <urllib3.connectionpool.HTTPSConnectionPool object at 0x104099350>, method = 'POST', url = '/api/v5/addons/upload/'
body = b'--bee28341e3d76b1092b55cb2014a73c2\r\nContent-Disposition: form-data; name="channel"\r\n\r\nlisted\r\n--bee28341e3d7...5\x06\x00\x00\x00\x00\x01\x00\x01\x00;\x00\x00\x00\xbe\x00\x00\x00\x00\x00\r\n--bee28341e3d76b1092b55cb2014a73c2--\r\n'
headers = {'User-Agent': 'python-requests/2.32.0', 'Accept-Encoding': 'gzip, deflate', 'Accept': '*/*', 'Connection': 'keep-aliv...j0yuvakt3v', 'Content-Length': '517', 'Content-Type': 'multipart/form-data; boundary=bee28341e3d76b1092b55cb2014a73c2'}
retries = Retry(total=0, connect=None, read=False, redirect=None, status=None), redirect = False, assert_same_host = False, timeout = Timeout(connect=None, read=None, total=None), pool_timeout = None
release_conn = False, chunked = False, body_pos = None, preload_content = False, decode_content = False, response_kw = {}
parsed_url = Url(scheme=None, auth=None, host=None, port=None, path='/api/v5/addons/upload/', query=None, fragment=None), destination_scheme = None, conn = None, release_this_conn = True
http_tunnel_required = False, err = None, clean_exit = False

def urlopen( # type: ignore[override]
self,
method: str,
url: str,
body: _TYPE_BODY | None = None,
headers: typing.Mapping[str, str] | None = None,
retries: Retry | bool | int | None = None,
redirect: bool = True,
assert_same_host: bool = True,
timeout: _TYPE_TIMEOUT = _DEFAULT_TIMEOUT,
pool_timeout: int | None = None,
release_conn: bool | None = None,
chunked: bool = False,
body_pos: _TYPE_BODY_POSITION | None = None,
preload_content: bool = True,
decode_content: bool = True,
**response_kw: typing.Any,
) -> BaseHTTPResponse:
"""
Get a connection from the pool and perform an HTTP request. This is the
lowest level call for making a request, so you'll need to specify all
the raw details.

.. note::

More commonly, it's appropriate to use a convenience method
such as :meth:`request`.

.. note::

`release_conn` will only behave as expected if
`preload_content=False` because we want to make
`preload_content=False` the default behaviour someday soon without
breaking backwards compatibility.

:param method:
HTTP request method (such as GET, POST, PUT, etc.)

:param url:
The URL to perform the request on.

:param body:
Data to send in the request body, either :class:`str`, :class:`bytes`,
an iterable of :class:`str`/:class:`bytes`, or a file-like object.

:param headers:
Dictionary of custom headers to send, such as User-Agent,
If-None-Match, etc. If None, pool headers are used. If provided,
these headers completely replace any pool-specific headers.

:param retries:
Configure the number of retries to allow before raising a
:class:`~urllib3.exceptions.MaxRetryError` exception.

If ``None`` (default) will retry 3 times, see ``Retry.DEFAULT``. Pass a
:class:`~urllib3.util.retry.Retry` object for fine-grained control
over different types of retries.
Pass an integer number to retry connection errors that many times,
but no other types of errors. Pass zero to never retry.

If ``False``, then retries are disabled and any exception is raised
immediately. Also, instead of raising a MaxRetryError on redirects,
the redirect response will be returned.

:type retries: :class:`~urllib3.util.retry.Retry`, False, or an int.

:param redirect:
If True, automatically handle redirects (status codes 301, 302,
303, 307, 308). Each redirect counts as a retry. Disabling retries
will disable redirect, too.

:param assert_same_host:
If ``True``, will make sure that the host of the pool requests is
consistent else will raise HostChangedError. When ``False``, you can
use the pool on an HTTP proxy and request foreign hosts.

:param timeout:
If specified, overrides the default timeout for this one
request. It may be a float (in seconds) or an instance of
:class:`urllib3.util.Timeout`.

:param pool_timeout:
If set and the pool is set to block=True, then this method will
block for ``pool_timeout`` seconds and raise EmptyPoolError if no
connection is available within the time period.

:param bool preload_content:
If True, the response's body will be preloaded into memory.

:param bool decode_content:
If True, will attempt to decode the body based on the
'content-encoding' header.

:param release_conn:
If False, then the urlopen call will not release the connection
back into the pool once a response is received (but will release if
you read the entire contents of the response such as when
`preload_content=True`). This is useful if you're not preloading
the response's content immediately. You will need to call
``r.release_conn()`` on the response ``r`` to return the connection
back into the pool. If None, it takes the value of ``preload_content``
which defaults to ``True``.

:param bool chunked:
If True, urllib3 will send the body using chunked transfer
encoding. Otherwise, urllib3 will send the body using the standard
content-length form. Defaults to False.

:param int body_pos:
Position to seek to in file-like body in the event of a retry or
redirect. Typically this won't need to be set because urllib3 will
auto-populate the value when needed.
"""
parsed_url = parse_url(url)
destination_scheme = parsed_url.scheme

if headers is None:
headers = self.headers

if not isinstance(retries, Retry):
retries = Retry.from_int(retries, redirect=redirect, default=self.retries)

if release_conn is None:
release_conn = preload_content

# Check host
if assert_same_host and not self.is_same_host(url):
raise HostChangedError(self, url, retries)

# Ensure that the URL we're connecting to is properly encoded
if url.startswith("/"):
url = to_str(_encode_target(url))
else:
url = to_str(parsed_url.url)

conn = None

# Track whether `conn` needs to be released before
# returning/raising/recursing. Update this variable if necessary, and
# leave `release_conn` constant throughout the function. That way, if
# the function recurses, the original value of `release_conn` will be
# passed down into the recursive call, and its value will be respected.
#
# See issue #651 [1] for details.
#
# [1] <https://github.com/urllib3/urllib3/issues/651>
release_this_conn = release_conn

http_tunnel_required = connection_requires_http_tunnel(
self.proxy, self.proxy_config, destination_scheme
)

# Merge the proxy headers. Only done when not using HTTP CONNECT. We
# have to copy the headers dict so we can safely change it without those
# changes being reflected in anyone else's copy.
if not http_tunnel_required:
headers = headers.copy() # type: ignore[attr-defined]
headers.update(self.proxy_headers) # type: ignore[union-attr]

# Must keep the exception bound to a separate variable or else Python 3
# complains about UnboundLocalError.
err = None

# Keep track of whether we cleanly exited the except block. This
# ensures we do proper cleanup in finally.
clean_exit = False

# Rewind body position, if needed. Record current position
# for future rewinds in the event of a redirect/retry.
body_pos = set_file_position(body, body_pos)

try:
# Request a connection from the queue.
timeout_obj = self._get_timeout(timeout)
conn = self._get_conn(timeout=pool_timeout)

conn.timeout = timeout_obj.connect_timeout # type: ignore[assignment]

# Is this a closed/new connection that requires CONNECT tunnelling?
if self.proxy is not None and http_tunnel_required and conn.is_closed:
try:
self._prepare_proxy(conn)
except (BaseSSLError, OSError, SocketTimeout) as e:
self._raise_timeout(
err=e, url=self.proxy.url, timeout_value=conn.timeout
)
raise

# If we're going to release the connection in ``finally:``, then
# the response doesn't need to know about the connection. Otherwise
# it will also try to release it and we'll have a double-release
# mess.
response_conn = conn if not release_conn else None

# Make the request on the HTTPConnection object
> response = self._make_request(
conn,
method,
url,
timeout=timeout_obj,
body=body,
headers=headers,
chunked=chunked,
retries=retries,
response_conn=response_conn,
preload_content=preload_content,
decode_content=decode_content,
**response_kw,
)

venv/lib/python3.11/site-packages/urllib3/connectionpool.py:789:
_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _
venv/lib/python3.11/site-packages/urllib3/connectionpool.py:490: in _make_request
raise new_e
venv/lib/python3.11/site-packages/urllib3/connectionpool.py:466: in _make_request
self._validate_conn(conn)
venv/lib/python3.11/site-packages/urllib3/connectionpool.py:1095: in _validate_conn
conn.connect()
venv/lib/python3.11/site-packages/urllib3/connection.py:615: in connect
self.sock = sock = self._new_conn()
_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _

self = <urllib3.connection.HTTPSConnection object at 0x104099c50>

def _new_conn(self) -> socket.socket:
"""Establish a socket connection and set nodelay settings on it.

:return: New socket connection.
"""
try:
sock = connection.create_connection(
(self._dns_host, self.port),
self.timeout,
source_address=self.source_address,
socket_options=self.socket_options,
)
except socket.gaierror as e:
> raise NameResolutionError(self.host, self, e) from e
E urllib3.exceptions.NameResolutionError: <urllib3.connection.HTTPSConnection object at 0x104099c50>: Failed to resolve 'addons.allizom.org' ([Errno 8] nodename nor servname provided, or not known)

venv/lib/python3.11/site-packages/urllib3/connection.py:203: NameResolutionError

The above exception was the direct cause of the following exception:

self = <requests.adapters.HTTPAdapter object at 0x10409ac50>, request = <PreparedRequest [POST]>, stream = False, timeout = Timeout(connect=None, read=None, total=None), verify = True, cert = None
proxies = OrderedDict()

def send(
self, request, stream=False, timeout=None, verify=True, cert=None, proxies=None
):
"""Sends PreparedRequest object. Returns Response object.

:param request: The :class:`PreparedRequest <PreparedRequest>` being sent.
:param stream: (optional) Whether to stream the request content.
:param timeout: (optional) How long to wait for the server to send
data before giving up, as a float, or a :ref:`(connect timeout,
read timeout) <timeouts>` tuple.
:type timeout: float or tuple or urllib3 Timeout object
:param verify: (optional) Either a boolean, in which case it controls whether
we verify the server's TLS certificate, or a string, in which case it
must be a path to a CA bundle to use
:param cert: (optional) Any user-provided SSL certificate to be trusted.
:param proxies: (optional) The proxies dictionary to apply to the request.
:rtype: requests.Response
"""

try:
conn = self._get_connection(request, verify, proxies=proxies, cert=cert)
except LocationValueError as e:
raise InvalidURL(e, request=request)

self.cert_verify(conn, request.url, verify, cert)
url = self.request_url(request, proxies)
self.add_headers(
request,
stream=stream,
timeout=timeout,
verify=verify,
cert=cert,
proxies=proxies,
)

chunked = not (request.body is None or "Content-Length" in request.headers)

if isinstance(timeout, tuple):
try:
connect, read = timeout
timeout = TimeoutSauce(connect=connect, read=read)
except ValueError:
raise ValueError(
f"Invalid timeout {timeout}. Pass a (connect, read) timeout tuple, "
f"or a single float to set both timeouts to the same value."
)
elif isinstance(timeout, TimeoutSauce):
pass
else:
timeout = TimeoutSauce(connect=timeout, read=timeout)

try:
> resp = conn.urlopen(
method=request.method,
url=url,
body=request.body,
headers=request.headers,
redirect=False,
assert_same_host=False,
preload_content=False,
decode_content=False,
retries=self.max_retries,
timeout=timeout,
chunked=chunked,
)

venv/lib/python3.11/site-packages/requests/adapters.py:564:
_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _
venv/lib/python3.11/site-packages/urllib3/connectionpool.py:843: in urlopen
retries = retries.increment(
_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _

self = Retry(total=0, connect=None, read=False, redirect=None, status=None), method = 'POST', url = '/api/v5/addons/upload/', response = None
error = NameResolutionError("<urllib3.connection.HTTPSConnection object at 0x104099c50>: Failed to resolve 'addons.allizom.org' ([Errno 8] nodename nor servname provided, or not known)")
_pool = <urllib3.connectionpool.HTTPSConnectionPool object at 0x104099350>, _stacktrace = <traceback object at 0x10409abc0>

def increment(
self,
method: str | None = None,
url: str | None = None,
response: BaseHTTPResponse | None = None,
error: Exception | None = None,
_pool: ConnectionPool | None = None,
_stacktrace: TracebackType | None = None,
) -> Self:
"""Return a new Retry object with incremented retry counters.

:param response: A response object, or None, if the server did not
return a response.
:type response: :class:`~urllib3.response.BaseHTTPResponse`
:param Exception error: An error encountered during the request, or
None if the response was received successfully.

:return: A new ``Retry`` object.
"""
if self.total is False and error:
# Disabled, indicate to re-raise the error.
raise reraise(type(error), error, _stacktrace)

total = self.total
if total is not None:
total -= 1

connect = self.connect
read = self.read
redirect = self.redirect
status_count = self.status
other = self.other
cause = "unknown"
status = None
redirect_location = None

if error and self._is_connection_error(error):
# Connect retry?
if connect is False:
raise reraise(type(error), error, _stacktrace)
elif connect is not None:
connect -= 1

elif error and self._is_read_error(error):
# Read retry?
if read is False or method is None or not self._is_method_retryable(method):
raise reraise(type(error), error, _stacktrace)
elif read is not None:
read -= 1

elif error:
# Other retry?
if other is not None:
other -= 1

elif response and response.get_redirect_location():
# Redirect retry?
if redirect is not None:
redirect -= 1
cause = "too many redirects"
response_redirect_location = response.get_redirect_location()
if response_redirect_location:
redirect_location = response_redirect_location
status = response.status

else:
# Incrementing because of a server error like a 500 in
# status_forcelist and the given method is in the allowed_methods
cause = ResponseError.GENERIC_ERROR
if response and response.status:
if status_count is not None:
status_count -= 1
cause = ResponseError.SPECIFIC_ERROR.format(status_code=response.status)
status = response.status

history = self.history + (
RequestHistory(method, url, error, status, redirect_location),
)

new_retry = self.new(
total=total,
connect=connect,
read=read,
redirect=redirect,
status=status_count,
other=other,
history=history,
)

if new_retry.is_exhausted():
reason = error or ResponseError(cause)
> raise MaxRetryError(_pool, url, reason) from reason # type: ignore[arg-type]
E urllib3.exceptions.MaxRetryError: HTTPSConnectionPool(host='addons.allizom.org', port=443): Max retries exceeded with url: /api/v5/addons/upload/ (Caused by NameResolutionError("<urllib3.connection.HTTPSConnection object at 0x104099c50>: Failed to resolve 'addons.allizom.org' ([Errno 8] nodename nor servname provided, or not known)"))

venv/lib/python3.11/site-packages/urllib3/util/retry.py:519: MaxRetryError

During handling of the above exception, another exception occurred:

base_url = 'https://addons.allizom.org', session_auth = 'ldvd5ag27bkfpukx6rn2lcj0yuvakt3v', guid = 'reserved_guid@temporary-addon'

@pytest.mark.parametrize(
"guid",
[
"reserved_guid@mozilla.com",
"reserved_guid@mozilla.org",
"reserved_guid@pioneer.mozilla.org",
"reserved_guid@search.mozilla.org",
"reserved_guid@shield.mozilla.com",
"reserved_guid@shield.mozilla.org",
"reserved_guid@mozillaonline.com",
"reserved_guid@mozillafoundation.org",
"reserved_guid@rally.mozilla.org",
"reserved_guid@temporary-addon",
"reserved_guid@mozac.org",
],
)
@pytest.mark.serial
@pytest.mark.create_session("api_user")
def test_submit_addon_with_reserved_guid(base_url, session_auth, guid):
"""Upload an addon that has a reserved guid suffix, unavailable for regular users"""
manifest = {
**payloads.minimal_manifest,
"name": "Reserved guid",
"browser_specific_settings": {"gecko": {"id": guid}},
}
api_helpers.make_addon(manifest)
with open("sample-addons/make-addon.zip", "rb") as file:
> upload = requests.post(
url=f"{base_url}{_upload}",
headers={"Authorization": f"Session {session_auth}"},
files={"upload": file},
data={"channel": "listed"},
)

tests/api_w/test_addon_uploads.py:392:
_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _
venv/lib/python3.11/site-packages/requests/api.py:115: in post
return request("post", url, data=data, json=json, **kwargs)
venv/lib/python3.11/site-packages/requests/api.py:59: in request
return session.request(method=method, url=url, **kwargs)
venv/lib/python3.11/site-packages/requests/sessions.py:589: in request
resp = self.send(prep, **send_kwargs)
venv/lib/python3.11/site-packages/requests/sessions.py:703: in send
r = adapter.send(request, **kwargs)
_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _

self = <requests.adapters.HTTPAdapter object at 0x10409ac50>, request = <PreparedRequest [POST]>, stream = False, timeout = Timeout(connect=None, read=None, total=None), verify = True, cert = None
proxies = OrderedDict()

def send(
self, request, stream=False, timeout=None, verify=True, cert=None, proxies=None
):
"""Sends PreparedRequest object. Returns Response object.

:param request: The :class:`PreparedRequest <PreparedRequest>` being sent.
:param stream: (optional) Whether to stream the request content.
:param timeout: (optional) How long to wait for the server to send
data before giving up, as a float, or a :ref:`(connect timeout,
read timeout) <timeouts>` tuple.
:type timeout: float or tuple or urllib3 Timeout object
:param verify: (optional) Either a boolean, in which case it controls whether
we verify the server's TLS certificate, or a string, in which case it
must be a path to a CA bundle to use
:param cert: (optional) Any user-provided SSL certificate to be trusted.
:param proxies: (optional) The proxies dictionary to apply to the request.
:rtype: requests.Response
"""

try:
conn = self._get_connection(request, verify, proxies=proxies, cert=cert)
except LocationValueError as e:
raise InvalidURL(e, request=request)

self.cert_verify(conn, request.url, verify, cert)
url = self.request_url(request, proxies)
self.add_headers(
request,
stream=stream,
timeout=timeout,
verify=verify,
cert=cert,
proxies=proxies,
)

chunked = not (request.body is None or "Content-Length" in request.headers)

if isinstance(timeout, tuple):
try:
connect, read = timeout
timeout = TimeoutSauce(connect=connect, read=read)
except ValueError:
raise ValueError(
f"Invalid timeout {timeout}. Pass a (connect, read) timeout tuple, "
f"or a single float to set both timeouts to the same value."
)
elif isinstance(timeout, TimeoutSauce):
pass
else:
timeout = TimeoutSauce(connect=timeout, read=timeout)

try:
resp = conn.urlopen(
method=request.method,
url=url,
body=request.body,
headers=request.headers,
redirect=False,
assert_same_host=False,
preload_content=False,
decode_content=False,
retries=self.max_retries,
timeout=timeout,
chunked=chunked,
)

except (ProtocolError, OSError) as err:
raise ConnectionError(err, request=request)

except MaxRetryError as e:
if isinstance(e.reason, ConnectTimeoutError):
# TODO: Remove this in 3.0.0: see #2811
if not isinstance(e.reason, NewConnectionError):
raise ConnectTimeout(e, request=request)

if isinstance(e.reason, ResponseError):
raise RetryError(e, request=request)

if isinstance(e.reason, _ProxyError):
raise ProxyError(e, request=request)

if isinstance(e.reason, _SSLError):
# This branch is for urllib3 v1.22 and later.
raise SSLError(e, request=request)

> raise ConnectionError(e, request=request)
E requests.exceptions.ConnectionError: HTTPSConnectionPool(host='addons.allizom.org', port=443): Max retries exceeded with url: /api/v5/addons/upload/ (Caused by NameResolutionError("<urllib3.connection.HTTPSConnection object at 0x104099c50>: Failed to resolve 'addons.allizom.org' ([Errno 8] nodename nor servname provided, or not known)"))

venv/lib/python3.11/site-packages/requests/adapters.py:597: ConnectionError
------------------------------Captured stdout call------------------------------
Manifest content: {'manifest_version': 2, 'version': '1.0', 'name': 'Reserved guid', 'browser_specific_settings': {'gecko': {'id': 'reserved_guid@temporary-addon'}}}
Failed tests/api_w/test_addon_uploads.py::test_submit_addon_with_reserved_guid[reserved_guid@mozac.org] 0.01
self = <urllib3.connection.HTTPSConnection object at 0x103dee390>

def _new_conn(self) -> socket.socket:
"""Establish a socket connection and set nodelay settings on it.

:return: New socket connection.
"""
try:
> sock = connection.create_connection(
(self._dns_host, self.port),
self.timeout,
source_address=self.source_address,
socket_options=self.socket_options,
)

venv/lib/python3.11/site-packages/urllib3/connection.py:196:
_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _
venv/lib/python3.11/site-packages/urllib3/util/connection.py:60: in create_connection
for res in socket.getaddrinfo(host, port, family, socket.SOCK_STREAM):
_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _

host = 'addons.allizom.org', port = 443, family = <AddressFamily.AF_UNSPEC: 0>, type = <SocketKind.SOCK_STREAM: 1>, proto = 0, flags = 0

def getaddrinfo(host, port, family=0, type=0, proto=0, flags=0):
"""Resolve host and port into list of address info entries.

Translate the host/port argument into a sequence of 5-tuples that contain
all the necessary arguments for creating a socket connected to that service.
host is a domain name, a string representation of an IPv4/v6 address or
None. port is a string service name such as 'http', a numeric port number or
None. By passing None as the value of host and port, you can pass NULL to
the underlying C API.

The family, type and proto arguments can be optionally specified in order to
narrow the list of addresses returned. Passing zero as a value for each of
these arguments selects the full range of results.
"""
# We override this function since we want to translate the numeric family
# and socket type values to enum constants.
addrlist = []
> for res in _socket.getaddrinfo(host, port, family, type, proto, flags):
E socket.gaierror: [Errno 8] nodename nor servname provided, or not known

/Library/Frameworks/Python.framework/Versions/3.11/lib/python3.11/socket.py:962: gaierror

The above exception was the direct cause of the following exception:

self = <urllib3.connectionpool.HTTPSConnectionPool object at 0x103def690>, method = 'POST', url = '/api/v5/addons/upload/'
body = b'--32eaba0d69525df07ddcbca75ece5f51\r\nContent-Disposition: form-data; name="channel"\r\n\r\nlisted\r\n--32eaba0d6952...5\x06\x00\x00\x00\x00\x01\x00\x01\x00;\x00\x00\x00\xb8\x00\x00\x00\x00\x00\r\n--32eaba0d69525df07ddcbca75ece5f51--\r\n'
headers = {'User-Agent': 'python-requests/2.32.0', 'Accept-Encoding': 'gzip, deflate', 'Accept': '*/*', 'Connection': 'keep-aliv...j0yuvakt3v', 'Content-Length': '511', 'Content-Type': 'multipart/form-data; boundary=32eaba0d69525df07ddcbca75ece5f51'}
retries = Retry(total=0, connect=None, read=False, redirect=None, status=None), redirect = False, assert_same_host = False, timeout = Timeout(connect=None, read=None, total=None), pool_timeout = None
release_conn = False, chunked = False, body_pos = None, preload_content = False, decode_content = False, response_kw = {}
parsed_url = Url(scheme=None, auth=None, host=None, port=None, path='/api/v5/addons/upload/', query=None, fragment=None), destination_scheme = None, conn = None, release_this_conn = True
http_tunnel_required = False, err = None, clean_exit = False

def urlopen( # type: ignore[override]
self,
method: str,
url: str,
body: _TYPE_BODY | None = None,
headers: typing.Mapping[str, str] | None = None,
retries: Retry | bool | int | None = None,
redirect: bool = True,
assert_same_host: bool = True,
timeout: _TYPE_TIMEOUT = _DEFAULT_TIMEOUT,
pool_timeout: int | None = None,
release_conn: bool | None = None,
chunked: bool = False,
body_pos: _TYPE_BODY_POSITION | None = None,
preload_content: bool = True,
decode_content: bool = True,
**response_kw: typing.Any,
) -> BaseHTTPResponse:
"""
Get a connection from the pool and perform an HTTP request. This is the
lowest level call for making a request, so you'll need to specify all
the raw details.

.. note::

More commonly, it's appropriate to use a convenience method
such as :meth:`request`.

.. note::

`release_conn` will only behave as expected if
`preload_content=False` because we want to make
`preload_content=False` the default behaviour someday soon without
breaking backwards compatibility.

:param method:
HTTP request method (such as GET, POST, PUT, etc.)

:param url:
The URL to perform the request on.

:param body:
Data to send in the request body, either :class:`str`, :class:`bytes`,
an iterable of :class:`str`/:class:`bytes`, or a file-like object.

:param headers:
Dictionary of custom headers to send, such as User-Agent,
If-None-Match, etc. If None, pool headers are used. If provided,
these headers completely replace any pool-specific headers.

:param retries:
Configure the number of retries to allow before raising a
:class:`~urllib3.exceptions.MaxRetryError` exception.

If ``None`` (default) will retry 3 times, see ``Retry.DEFAULT``. Pass a
:class:`~urllib3.util.retry.Retry` object for fine-grained control
over different types of retries.
Pass an integer number to retry connection errors that many times,
but no other types of errors. Pass zero to never retry.

If ``False``, then retries are disabled and any exception is raised
immediately. Also, instead of raising a MaxRetryError on redirects,
the redirect response will be returned.

:type retries: :class:`~urllib3.util.retry.Retry`, False, or an int.

:param redirect:
If True, automatically handle redirects (status codes 301, 302,
303, 307, 308). Each redirect counts as a retry. Disabling retries
will disable redirect, too.

:param assert_same_host:
If ``True``, will make sure that the host of the pool requests is
consistent else will raise HostChangedError. When ``False``, you can
use the pool on an HTTP proxy and request foreign hosts.

:param timeout:
If specified, overrides the default timeout for this one
request. It may be a float (in seconds) or an instance of
:class:`urllib3.util.Timeout`.

:param pool_timeout:
If set and the pool is set to block=True, then this method will
block for ``pool_timeout`` seconds and raise EmptyPoolError if no
connection is available within the time period.

:param bool preload_content:
If True, the response's body will be preloaded into memory.

:param bool decode_content:
If True, will attempt to decode the body based on the
'content-encoding' header.

:param release_conn:
If False, then the urlopen call will not release the connection
back into the pool once a response is received (but will release if
you read the entire contents of the response such as when
`preload_content=True`). This is useful if you're not preloading
the response's content immediately. You will need to call
``r.release_conn()`` on the response ``r`` to return the connection
back into the pool. If None, it takes the value of ``preload_content``
which defaults to ``True``.

:param bool chunked:
If True, urllib3 will send the body using chunked transfer
encoding. Otherwise, urllib3 will send the body using the standard
content-length form. Defaults to False.

:param int body_pos:
Position to seek to in file-like body in the event of a retry or
redirect. Typically this won't need to be set because urllib3 will
auto-populate the value when needed.
"""
parsed_url = parse_url(url)
destination_scheme = parsed_url.scheme

if headers is None:
headers = self.headers

if not isinstance(retries, Retry):
retries = Retry.from_int(retries, redirect=redirect, default=self.retries)

if release_conn is None:
release_conn = preload_content

# Check host
if assert_same_host and not self.is_same_host(url):
raise HostChangedError(self, url, retries)

# Ensure that the URL we're connecting to is properly encoded
if url.startswith("/"):
url = to_str(_encode_target(url))
else:
url = to_str(parsed_url.url)

conn = None

# Track whether `conn` needs to be released before
# returning/raising/recursing. Update this variable if necessary, and
# leave `release_conn` constant throughout the function. That way, if
# the function recurses, the original value of `release_conn` will be
# passed down into the recursive call, and its value will be respected.
#
# See issue #651 [1] for details.
#
# [1] <https://github.com/urllib3/urllib3/issues/651>
release_this_conn = release_conn

http_tunnel_required = connection_requires_http_tunnel(
self.proxy, self.proxy_config, destination_scheme
)

# Merge the proxy headers. Only done when not using HTTP CONNECT. We
# have to copy the headers dict so we can safely change it without those
# changes being reflected in anyone else's copy.
if not http_tunnel_required:
headers = headers.copy() # type: ignore[attr-defined]
headers.update(self.proxy_headers) # type: ignore[union-attr]

# Must keep the exception bound to a separate variable or else Python 3
# complains about UnboundLocalError.
err = None

# Keep track of whether we cleanly exited the except block. This
# ensures we do proper cleanup in finally.
clean_exit = False

# Rewind body position, if needed. Record current position
# for future rewinds in the event of a redirect/retry.
body_pos = set_file_position(body, body_pos)

try:
# Request a connection from the queue.
timeout_obj = self._get_timeout(timeout)
conn = self._get_conn(timeout=pool_timeout)

conn.timeout = timeout_obj.connect_timeout # type: ignore[assignment]

# Is this a closed/new connection that requires CONNECT tunnelling?
if self.proxy is not None and http_tunnel_required and conn.is_closed:
try:
self._prepare_proxy(conn)
except (BaseSSLError, OSError, SocketTimeout) as e:
self._raise_timeout(
err=e, url=self.proxy.url, timeout_value=conn.timeout
)
raise

# If we're going to release the connection in ``finally:``, then
# the response doesn't need to know about the connection. Otherwise
# it will also try to release it and we'll have a double-release
# mess.
response_conn = conn if not release_conn else None

# Make the request on the HTTPConnection object
> response = self._make_request(
conn,
method,
url,
timeout=timeout_obj,
body=body,
headers=headers,
chunked=chunked,
retries=retries,
response_conn=response_conn,
preload_content=preload_content,
decode_content=decode_content,
**response_kw,
)

venv/lib/python3.11/site-packages/urllib3/connectionpool.py:789:
_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _
venv/lib/python3.11/site-packages/urllib3/connectionpool.py:490: in _make_request
raise new_e
venv/lib/python3.11/site-packages/urllib3/connectionpool.py:466: in _make_request
self._validate_conn(conn)
venv/lib/python3.11/site-packages/urllib3/connectionpool.py:1095: in _validate_conn
conn.connect()
venv/lib/python3.11/site-packages/urllib3/connection.py:615: in connect
self.sock = sock = self._new_conn()
_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _

self = <urllib3.connection.HTTPSConnection object at 0x103dee390>

def _new_conn(self) -> socket.socket:
"""Establish a socket connection and set nodelay settings on it.

:return: New socket connection.
"""
try:
sock = connection.create_connection(
(self._dns_host, self.port),
self.timeout,
source_address=self.source_address,
socket_options=self.socket_options,
)
except socket.gaierror as e:
> raise NameResolutionError(self.host, self, e) from e
E urllib3.exceptions.NameResolutionError: <urllib3.connection.HTTPSConnection object at 0x103dee390>: Failed to resolve 'addons.allizom.org' ([Errno 8] nodename nor servname provided, or not known)

venv/lib/python3.11/site-packages/urllib3/connection.py:203: NameResolutionError

The above exception was the direct cause of the following exception:

self = <requests.adapters.HTTPAdapter object at 0x103dee690>, request = <PreparedRequest [POST]>, stream = False, timeout = Timeout(connect=None, read=None, total=None), verify = True, cert = None
proxies = OrderedDict()

def send(
self, request, stream=False, timeout=None, verify=True, cert=None, proxies=None
):
"""Sends PreparedRequest object. Returns Response object.

:param request: The :class:`PreparedRequest <PreparedRequest>` being sent.
:param stream: (optional) Whether to stream the request content.
:param timeout: (optional) How long to wait for the server to send
data before giving up, as a float, or a :ref:`(connect timeout,
read timeout) <timeouts>` tuple.
:type timeout: float or tuple or urllib3 Timeout object
:param verify: (optional) Either a boolean, in which case it controls whether
we verify the server's TLS certificate, or a string, in which case it
must be a path to a CA bundle to use
:param cert: (optional) Any user-provided SSL certificate to be trusted.
:param proxies: (optional) The proxies dictionary to apply to the request.
:rtype: requests.Response
"""

try:
conn = self._get_connection(request, verify, proxies=proxies, cert=cert)
except LocationValueError as e:
raise InvalidURL(e, request=request)

self.cert_verify(conn, request.url, verify, cert)
url = self.request_url(request, proxies)
self.add_headers(
request,
stream=stream,
timeout=timeout,
verify=verify,
cert=cert,
proxies=proxies,
)

chunked = not (request.body is None or "Content-Length" in request.headers)

if isinstance(timeout, tuple):
try:
connect, read = timeout
timeout = TimeoutSauce(connect=connect, read=read)
except ValueError:
raise ValueError(
f"Invalid timeout {timeout}. Pass a (connect, read) timeout tuple, "
f"or a single float to set both timeouts to the same value."
)
elif isinstance(timeout, TimeoutSauce):
pass
else:
timeout = TimeoutSauce(connect=timeout, read=timeout)

try:
> resp = conn.urlopen(
method=request.method,
url=url,
body=request.body,
headers=request.headers,
redirect=False,
assert_same_host=False,
preload_content=False,
decode_content=False,
retries=self.max_retries,
timeout=timeout,
chunked=chunked,
)

venv/lib/python3.11/site-packages/requests/adapters.py:564:
_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _
venv/lib/python3.11/site-packages/urllib3/connectionpool.py:843: in urlopen
retries = retries.increment(
_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _

self = Retry(total=0, connect=None, read=False, redirect=None, status=None), method = 'POST', url = '/api/v5/addons/upload/', response = None
error = NameResolutionError("<urllib3.connection.HTTPSConnection object at 0x103dee390>: Failed to resolve 'addons.allizom.org' ([Errno 8] nodename nor servname provided, or not known)")
_pool = <urllib3.connectionpool.HTTPSConnectionPool object at 0x103def690>, _stacktrace = <traceback object at 0x103dee340>

def increment(
self,
method: str | None = None,
url: str | None = None,
response: BaseHTTPResponse | None = None,
error: Exception | None = None,
_pool: ConnectionPool | None = None,
_stacktrace: TracebackType | None = None,
) -> Self:
"""Return a new Retry object with incremented retry counters.

:param response: A response object, or None, if the server did not
return a response.
:type response: :class:`~urllib3.response.BaseHTTPResponse`
:param Exception error: An error encountered during the request, or
None if the response was received successfully.

:return: A new ``Retry`` object.
"""
if self.total is False and error:
# Disabled, indicate to re-raise the error.
raise reraise(type(error), error, _stacktrace)

total = self.total
if total is not None:
total -= 1

connect = self.connect
read = self.read
redirect = self.redirect
status_count = self.status
other = self.other
cause = "unknown"
status = None
redirect_location = None

if error and self._is_connection_error(error):
# Connect retry?
if connect is False:
raise reraise(type(error), error, _stacktrace)
elif connect is not None:
connect -= 1

elif error and self._is_read_error(error):
# Read retry?
if read is False or method is None or not self._is_method_retryable(method):
raise reraise(type(error), error, _stacktrace)
elif read is not None:
read -= 1

elif error:
# Other retry?
if other is not None:
other -= 1

elif response and response.get_redirect_location():
# Redirect retry?
if redirect is not None:
redirect -= 1
cause = "too many redirects"
response_redirect_location = response.get_redirect_location()
if response_redirect_location:
redirect_location = response_redirect_location
status = response.status

else:
# Incrementing because of a server error like a 500 in
# status_forcelist and the given method is in the allowed_methods
cause = ResponseError.GENERIC_ERROR
if response and response.status:
if status_count is not None:
status_count -= 1
cause = ResponseError.SPECIFIC_ERROR.format(status_code=response.status)
status = response.status

history = self.history + (
RequestHistory(method, url, error, status, redirect_location),
)

new_retry = self.new(
total=total,
connect=connect,
read=read,
redirect=redirect,
status=status_count,
other=other,
history=history,
)

if new_retry.is_exhausted():
reason = error or ResponseError(cause)
> raise MaxRetryError(_pool, url, reason) from reason # type: ignore[arg-type]
E urllib3.exceptions.MaxRetryError: HTTPSConnectionPool(host='addons.allizom.org', port=443): Max retries exceeded with url: /api/v5/addons/upload/ (Caused by NameResolutionError("<urllib3.connection.HTTPSConnection object at 0x103dee390>: Failed to resolve 'addons.allizom.org' ([Errno 8] nodename nor servname provided, or not known)"))

venv/lib/python3.11/site-packages/urllib3/util/retry.py:519: MaxRetryError

During handling of the above exception, another exception occurred:

base_url = 'https://addons.allizom.org', session_auth = 'ldvd5ag27bkfpukx6rn2lcj0yuvakt3v', guid = 'reserved_guid@mozac.org'

@pytest.mark.parametrize(
"guid",
[
"reserved_guid@mozilla.com",
"reserved_guid@mozilla.org",
"reserved_guid@pioneer.mozilla.org",
"reserved_guid@search.mozilla.org",
"reserved_guid@shield.mozilla.com",
"reserved_guid@shield.mozilla.org",
"reserved_guid@mozillaonline.com",
"reserved_guid@mozillafoundation.org",
"reserved_guid@rally.mozilla.org",
"reserved_guid@temporary-addon",
"reserved_guid@mozac.org",
],
)
@pytest.mark.serial
@pytest.mark.create_session("api_user")
def test_submit_addon_with_reserved_guid(base_url, session_auth, guid):
"""Upload an addon that has a reserved guid suffix, unavailable for regular users"""
manifest = {
**payloads.minimal_manifest,
"name": "Reserved guid",
"browser_specific_settings": {"gecko": {"id": guid}},
}
api_helpers.make_addon(manifest)
with open("sample-addons/make-addon.zip", "rb") as file:
> upload = requests.post(
url=f"{base_url}{_upload}",
headers={"Authorization": f"Session {session_auth}"},
files={"upload": file},
data={"channel": "listed"},
)

tests/api_w/test_addon_uploads.py:392:
_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _
venv/lib/python3.11/site-packages/requests/api.py:115: in post
return request("post", url, data=data, json=json, **kwargs)
venv/lib/python3.11/site-packages/requests/api.py:59: in request
return session.request(method=method, url=url, **kwargs)
venv/lib/python3.11/site-packages/requests/sessions.py:589: in request
resp = self.send(prep, **send_kwargs)
venv/lib/python3.11/site-packages/requests/sessions.py:703: in send
r = adapter.send(request, **kwargs)
_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _

self = <requests.adapters.HTTPAdapter object at 0x103dee690>, request = <PreparedRequest [POST]>, stream = False, timeout = Timeout(connect=None, read=None, total=None), verify = True, cert = None
proxies = OrderedDict()

def send(
self, request, stream=False, timeout=None, verify=True, cert=None, proxies=None
):
"""Sends PreparedRequest object. Returns Response object.

:param request: The :class:`PreparedRequest <PreparedRequest>` being sent.
:param stream: (optional) Whether to stream the request content.
:param timeout: (optional) How long to wait for the server to send
data before giving up, as a float, or a :ref:`(connect timeout,
read timeout) <timeouts>` tuple.
:type timeout: float or tuple or urllib3 Timeout object
:param verify: (optional) Either a boolean, in which case it controls whether
we verify the server's TLS certificate, or a string, in which case it
must be a path to a CA bundle to use
:param cert: (optional) Any user-provided SSL certificate to be trusted.
:param proxies: (optional) The proxies dictionary to apply to the request.
:rtype: requests.Response
"""

try:
conn = self._get_connection(request, verify, proxies=proxies, cert=cert)
except LocationValueError as e:
raise InvalidURL(e, request=request)

self.cert_verify(conn, request.url, verify, cert)
url = self.request_url(request, proxies)
self.add_headers(
request,
stream=stream,
timeout=timeout,
verify=verify,
cert=cert,
proxies=proxies,
)

chunked = not (request.body is None or "Content-Length" in request.headers)

if isinstance(timeout, tuple):
try:
connect, read = timeout
timeout = TimeoutSauce(connect=connect, read=read)
except ValueError:
raise ValueError(
f"Invalid timeout {timeout}. Pass a (connect, read) timeout tuple, "
f"or a single float to set both timeouts to the same value."
)
elif isinstance(timeout, TimeoutSauce):
pass
else:
timeout = TimeoutSauce(connect=timeout, read=timeout)

try:
resp = conn.urlopen(
method=request.method,
url=url,
body=request.body,
headers=request.headers,
redirect=False,
assert_same_host=False,
preload_content=False,
decode_content=False,
retries=self.max_retries,
timeout=timeout,
chunked=chunked,
)

except (ProtocolError, OSError) as err:
raise ConnectionError(err, request=request)

except MaxRetryError as e:
if isinstance(e.reason, ConnectTimeoutError):
# TODO: Remove this in 3.0.0: see #2811
if not isinstance(e.reason, NewConnectionError):
raise ConnectTimeout(e, request=request)

if isinstance(e.reason, ResponseError):
raise RetryError(e, request=request)

if isinstance(e.reason, _ProxyError):
raise ProxyError(e, request=request)

if isinstance(e.reason, _SSLError):
# This branch is for urllib3 v1.22 and later.
raise SSLError(e, request=request)

> raise ConnectionError(e, request=request)
E requests.exceptions.ConnectionError: HTTPSConnectionPool(host='addons.allizom.org', port=443): Max retries exceeded with url: /api/v5/addons/upload/ (Caused by NameResolutionError("<urllib3.connection.HTTPSConnection object at 0x103dee390>: Failed to resolve 'addons.allizom.org' ([Errno 8] nodename nor servname provided, or not known)"))

venv/lib/python3.11/site-packages/requests/adapters.py:597: ConnectionError
------------------------------Captured stdout call------------------------------
Manifest content: {'manifest_version': 2, 'version': '1.0', 'name': 'Reserved guid', 'browser_specific_settings': {'gecko': {'id': 'reserved_guid@mozac.org'}}}
Failed tests/api_w/test_addon_uploads.py::test_upload_extension_with_duplicate_guid 0.01
self = <urllib3.connection.HTTPSConnection object at 0x103cf3450>

def _new_conn(self) -> socket.socket:
"""Establish a socket connection and set nodelay settings on it.

:return: New socket connection.
"""
try:
> sock = connection.create_connection(
(self._dns_host, self.port),
self.timeout,
source_address=self.source_address,
socket_options=self.socket_options,
)

venv/lib/python3.11/site-packages/urllib3/connection.py:196:
_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _
venv/lib/python3.11/site-packages/urllib3/util/connection.py:60: in create_connection
for res in socket.getaddrinfo(host, port, family, socket.SOCK_STREAM):
_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _

host = 'addons.allizom.org', port = 443, family = <AddressFamily.AF_UNSPEC: 0>, type = <SocketKind.SOCK_STREAM: 1>, proto = 0, flags = 0

def getaddrinfo(host, port, family=0, type=0, proto=0, flags=0):
"""Resolve host and port into list of address info entries.

Translate the host/port argument into a sequence of 5-tuples that contain
all the necessary arguments for creating a socket connected to that service.
host is a domain name, a string representation of an IPv4/v6 address or
None. port is a string service name such as 'http', a numeric port number or
None. By passing None as the value of host and port, you can pass NULL to
the underlying C API.

The family, type and proto arguments can be optionally specified in order to
narrow the list of addresses returned. Passing zero as a value for each of
these arguments selects the full range of results.
"""
# We override this function since we want to translate the numeric family
# and socket type values to enum constants.
addrlist = []
> for res in _socket.getaddrinfo(host, port, family, type, proto, flags):
E socket.gaierror: [Errno 8] nodename nor servname provided, or not known

/Library/Frameworks/Python.framework/Versions/3.11/lib/python3.11/socket.py:962: gaierror

The above exception was the direct cause of the following exception:

self = <urllib3.connectionpool.HTTPSConnectionPool object at 0x103cf2c90>, method = 'POST', url = '/api/v5/addons/upload/'
body = b'--2adbac3c0ddd17c2fc679a81c09906a9\r\nContent-Disposition: form-data; name="channel"\r\n\r\nlisted\r\n--2adbac3c0ddd...5\x06\x00\x00\x00\x00\x01\x00\x01\x00;\x00\x00\x00\xb3\x00\x00\x00\x00\x00\r\n--2adbac3c0ddd17c2fc679a81c09906a9--\r\n'
headers = {'User-Agent': 'python-requests/2.32.0', 'Accept-Encoding': 'gzip, deflate', 'Accept': '*/*', 'Connection': 'keep-aliv...j0yuvakt3v', 'Content-Length': '506', 'Content-Type': 'multipart/form-data; boundary=2adbac3c0ddd17c2fc679a81c09906a9'}
retries = Retry(total=0, connect=None, read=False, redirect=None, status=None), redirect = False, assert_same_host = False, timeout = Timeout(connect=None, read=None, total=None), pool_timeout = None
release_conn = False, chunked = False, body_pos = None, preload_content = False, decode_content = False, response_kw = {}
parsed_url = Url(scheme=None, auth=None, host=None, port=None, path='/api/v5/addons/upload/', query=None, fragment=None), destination_scheme = None, conn = None, release_this_conn = True
http_tunnel_required = False, err = None, clean_exit = False

def urlopen( # type: ignore[override]
self,
method: str,
url: str,
body: _TYPE_BODY | None = None,
headers: typing.Mapping[str, str] | None = None,
retries: Retry | bool | int | None = None,
redirect: bool = True,
assert_same_host: bool = True,
timeout: _TYPE_TIMEOUT = _DEFAULT_TIMEOUT,
pool_timeout: int | None = None,
release_conn: bool | None = None,
chunked: bool = False,
body_pos: _TYPE_BODY_POSITION | None = None,
preload_content: bool = True,
decode_content: bool = True,
**response_kw: typing.Any,
) -> BaseHTTPResponse:
"""
Get a connection from the pool and perform an HTTP request. This is the
lowest level call for making a request, so you'll need to specify all
the raw details.

.. note::

More commonly, it's appropriate to use a convenience method
such as :meth:`request`.

.. note::

`release_conn` will only behave as expected if
`preload_content=False` because we want to make
`preload_content=False` the default behaviour someday soon without
breaking backwards compatibility.

:param method:
HTTP request method (such as GET, POST, PUT, etc.)

:param url:
The URL to perform the request on.

:param body:
Data to send in the request body, either :class:`str`, :class:`bytes`,
an iterable of :class:`str`/:class:`bytes`, or a file-like object.

:param headers:
Dictionary of custom headers to send, such as User-Agent,
If-None-Match, etc. If None, pool headers are used. If provided,
these headers completely replace any pool-specific headers.

:param retries:
Configure the number of retries to allow before raising a
:class:`~urllib3.exceptions.MaxRetryError` exception.

If ``None`` (default) will retry 3 times, see ``Retry.DEFAULT``. Pass a
:class:`~urllib3.util.retry.Retry` object for fine-grained control
over different types of retries.
Pass an integer number to retry connection errors that many times,
but no other types of errors. Pass zero to never retry.

If ``False``, then retries are disabled and any exception is raised
immediately. Also, instead of raising a MaxRetryError on redirects,
the redirect response will be returned.

:type retries: :class:`~urllib3.util.retry.Retry`, False, or an int.

:param redirect:
If True, automatically handle redirects (status codes 301, 302,
303, 307, 308). Each redirect counts as a retry. Disabling retries
will disable redirect, too.

:param assert_same_host:
If ``True``, will make sure that the host of the pool requests is
consistent else will raise HostChangedError. When ``False``, you can
use the pool on an HTTP proxy and request foreign hosts.

:param timeout:
If specified, overrides the default timeout for this one
request. It may be a float (in seconds) or an instance of
:class:`urllib3.util.Timeout`.

:param pool_timeout:
If set and the pool is set to block=True, then this method will
block for ``pool_timeout`` seconds and raise EmptyPoolError if no
connection is available within the time period.

:param bool preload_content:
If True, the response's body will be preloaded into memory.

:param bool decode_content:
If True, will attempt to decode the body based on the
'content-encoding' header.

:param release_conn:
If False, then the urlopen call will not release the connection
back into the pool once a response is received (but will release if
you read the entire contents of the response such as when
`preload_content=True`). This is useful if you're not preloading
the response's content immediately. You will need to call
``r.release_conn()`` on the response ``r`` to return the connection
back into the pool. If None, it takes the value of ``preload_content``
which defaults to ``True``.

:param bool chunked:
If True, urllib3 will send the body using chunked transfer
encoding. Otherwise, urllib3 will send the body using the standard
content-length form. Defaults to False.

:param int body_pos:
Position to seek to in file-like body in the event of a retry or
redirect. Typically this won't need to be set because urllib3 will
auto-populate the value when needed.
"""
parsed_url = parse_url(url)
destination_scheme = parsed_url.scheme

if headers is None:
headers = self.headers

if not isinstance(retries, Retry):
retries = Retry.from_int(retries, redirect=redirect, default=self.retries)

if release_conn is None:
release_conn = preload_content

# Check host
if assert_same_host and not self.is_same_host(url):
raise HostChangedError(self, url, retries)

# Ensure that the URL we're connecting to is properly encoded
if url.startswith("/"):
url = to_str(_encode_target(url))
else:
url = to_str(parsed_url.url)

conn = None

# Track whether `conn` needs to be released before
# returning/raising/recursing. Update this variable if necessary, and
# leave `release_conn` constant throughout the function. That way, if
# the function recurses, the original value of `release_conn` will be
# passed down into the recursive call, and its value will be respected.
#
# See issue #651 [1] for details.
#
# [1] <https://github.com/urllib3/urllib3/issues/651>
release_this_conn = release_conn

http_tunnel_required = connection_requires_http_tunnel(
self.proxy, self.proxy_config, destination_scheme
)

# Merge the proxy headers. Only done when not using HTTP CONNECT. We
# have to copy the headers dict so we can safely change it without those
# changes being reflected in anyone else's copy.
if not http_tunnel_required:
headers = headers.copy() # type: ignore[attr-defined]
headers.update(self.proxy_headers) # type: ignore[union-attr]

# Must keep the exception bound to a separate variable or else Python 3
# complains about UnboundLocalError.
err = None

# Keep track of whether we cleanly exited the except block. This
# ensures we do proper cleanup in finally.
clean_exit = False

# Rewind body position, if needed. Record current position
# for future rewinds in the event of a redirect/retry.
body_pos = set_file_position(body, body_pos)

try:
# Request a connection from the queue.
timeout_obj = self._get_timeout(timeout)
conn = self._get_conn(timeout=pool_timeout)

conn.timeout = timeout_obj.connect_timeout # type: ignore[assignment]

# Is this a closed/new connection that requires CONNECT tunnelling?
if self.proxy is not None and http_tunnel_required and conn.is_closed:
try:
self._prepare_proxy(conn)
except (BaseSSLError, OSError, SocketTimeout) as e:
self._raise_timeout(
err=e, url=self.proxy.url, timeout_value=conn.timeout
)
raise

# If we're going to release the connection in ``finally:``, then
# the response doesn't need to know about the connection. Otherwise
# it will also try to release it and we'll have a double-release
# mess.
response_conn = conn if not release_conn else None

# Make the request on the HTTPConnection object
> response = self._make_request(
conn,
method,
url,
timeout=timeout_obj,
body=body,
headers=headers,
chunked=chunked,
retries=retries,
response_conn=response_conn,
preload_content=preload_content,
decode_content=decode_content,
**response_kw,
)

venv/lib/python3.11/site-packages/urllib3/connectionpool.py:789:
_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _
venv/lib/python3.11/site-packages/urllib3/connectionpool.py:490: in _make_request
raise new_e
venv/lib/python3.11/site-packages/urllib3/connectionpool.py:466: in _make_request
self._validate_conn(conn)
venv/lib/python3.11/site-packages/urllib3/connectionpool.py:1095: in _validate_conn
conn.connect()
venv/lib/python3.11/site-packages/urllib3/connection.py:615: in connect
self.sock = sock = self._new_conn()
_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _

self = <urllib3.connection.HTTPSConnection object at 0x103cf3450>

def _new_conn(self) -> socket.socket:
"""Establish a socket connection and set nodelay settings on it.

:return: New socket connection.
"""
try:
sock = connection.create_connection(
(self._dns_host, self.port),
self.timeout,
source_address=self.source_address,
socket_options=self.socket_options,
)
except socket.gaierror as e:
> raise NameResolutionError(self.host, self, e) from e
E urllib3.exceptions.NameResolutionError: <urllib3.connection.HTTPSConnection object at 0x103cf3450>: Failed to resolve 'addons.allizom.org' ([Errno 8] nodename nor servname provided, or not known)

venv/lib/python3.11/site-packages/urllib3/connection.py:203: NameResolutionError

The above exception was the direct cause of the following exception:

self = <requests.adapters.HTTPAdapter object at 0x103cf3c10>, request = <PreparedRequest [POST]>, stream = False, timeout = Timeout(connect=None, read=None, total=None), verify = True, cert = None
proxies = OrderedDict()

def send(
self, request, stream=False, timeout=None, verify=True, cert=None, proxies=None
):
"""Sends PreparedRequest object. Returns Response object.

:param request: The :class:`PreparedRequest <PreparedRequest>` being sent.
:param stream: (optional) Whether to stream the request content.
:param timeout: (optional) How long to wait for the server to send
data before giving up, as a float, or a :ref:`(connect timeout,
read timeout) <timeouts>` tuple.
:type timeout: float or tuple or urllib3 Timeout object
:param verify: (optional) Either a boolean, in which case it controls whether
we verify the server's TLS certificate, or a string, in which case it
must be a path to a CA bundle to use
:param cert: (optional) Any user-provided SSL certificate to be trusted.
:param proxies: (optional) The proxies dictionary to apply to the request.
:rtype: requests.Response
"""

try:
conn = self._get_connection(request, verify, proxies=proxies, cert=cert)
except LocationValueError as e:
raise InvalidURL(e, request=request)

self.cert_verify(conn, request.url, verify, cert)
url = self.request_url(request, proxies)
self.add_headers(
request,
stream=stream,
timeout=timeout,
verify=verify,
cert=cert,
proxies=proxies,
)

chunked = not (request.body is None or "Content-Length" in request.headers)

if isinstance(timeout, tuple):
try:
connect, read = timeout
timeout = TimeoutSauce(connect=connect, read=read)
except ValueError:
raise ValueError(
f"Invalid timeout {timeout}. Pass a (connect, read) timeout tuple, "
f"or a single float to set both timeouts to the same value."
)
elif isinstance(timeout, TimeoutSauce):
pass
else:
timeout = TimeoutSauce(connect=timeout, read=timeout)

try:
> resp = conn.urlopen(
method=request.method,
url=url,
body=request.body,
headers=request.headers,
redirect=False,
assert_same_host=False,
preload_content=False,
decode_content=False,
retries=self.max_retries,
timeout=timeout,
chunked=chunked,
)

venv/lib/python3.11/site-packages/requests/adapters.py:564:
_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _
venv/lib/python3.11/site-packages/urllib3/connectionpool.py:843: in urlopen
retries = retries.increment(
_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _

self = Retry(total=0, connect=None, read=False, redirect=None, status=None), method = 'POST', url = '/api/v5/addons/upload/', response = None
error = NameResolutionError("<urllib3.connection.HTTPSConnection object at 0x103cf3450>: Failed to resolve 'addons.allizom.org' ([Errno 8] nodename nor servname provided, or not known)")
_pool = <urllib3.connectionpool.HTTPSConnectionPool object at 0x103cf2c90>, _stacktrace = <traceback object at 0x103cf0e00>

def increment(
self,
method: str | None = None,
url: str | None = None,
response: BaseHTTPResponse | None = None,
error: Exception | None = None,
_pool: ConnectionPool | None = None,
_stacktrace: TracebackType | None = None,
) -> Self:
"""Return a new Retry object with incremented retry counters.

:param response: A response object, or None, if the server did not
return a response.
:type response: :class:`~urllib3.response.BaseHTTPResponse`
:param Exception error: An error encountered during the request, or
None if the response was received successfully.

:return: A new ``Retry`` object.
"""
if self.total is False and error:
# Disabled, indicate to re-raise the error.
raise reraise(type(error), error, _stacktrace)

total = self.total
if total is not None:
total -= 1

connect = self.connect
read = self.read
redirect = self.redirect
status_count = self.status
other = self.other
cause = "unknown"
status = None
redirect_location = None

if error and self._is_connection_error(error):
# Connect retry?
if connect is False:
raise reraise(type(error), error, _stacktrace)
elif connect is not None:
connect -= 1

elif error and self._is_read_error(error):
# Read retry?
if read is False or method is None or not self._is_method_retryable(method):
raise reraise(type(error), error, _stacktrace)
elif read is not None:
read -= 1

elif error:
# Other retry?
if other is not None:
other -= 1

elif response and response.get_redirect_location():
# Redirect retry?
if redirect is not None:
redirect -= 1
cause = "too many redirects"
response_redirect_location = response.get_redirect_location()
if response_redirect_location:
redirect_location = response_redirect_location
status = response.status

else:
# Incrementing because of a server error like a 500 in
# status_forcelist and the given method is in the allowed_methods
cause = ResponseError.GENERIC_ERROR
if response and response.status:
if status_count is not None:
status_count -= 1
cause = ResponseError.SPECIFIC_ERROR.format(status_code=response.status)
status = response.status

history = self.history + (
RequestHistory(method, url, error, status, redirect_location),
)

new_retry = self.new(
total=total,
connect=connect,
read=read,
redirect=redirect,
status=status_count,
other=other,
history=history,
)

if new_retry.is_exhausted():
reason = error or ResponseError(cause)
> raise MaxRetryError(_pool, url, reason) from reason # type: ignore[arg-type]
E urllib3.exceptions.MaxRetryError: HTTPSConnectionPool(host='addons.allizom.org', port=443): Max retries exceeded with url: /api/v5/addons/upload/ (Caused by NameResolutionError("<urllib3.connection.HTTPSConnection object at 0x103cf3450>: Failed to resolve 'addons.allizom.org' ([Errno 8] nodename nor servname provided, or not known)"))

venv/lib/python3.11/site-packages/urllib3/util/retry.py:519: MaxRetryError

During handling of the above exception, another exception occurred:

base_url = 'https://addons.allizom.org', session_auth = 'ldvd5ag27bkfpukx6rn2lcj0yuvakt3v'
variables = {'4mb_addon_slug': '4mb_addon_slug', 'addon_detail_guid': '{446900e4-71c2-419f-a6a7-df9c091e268b}', 'addon_detail_id':...dd-ons must comply with Mozilla’s Add-on Policies and are subject to manual review at any time after submission.', ...}

@pytest.mark.serial
@pytest.mark.create_session("api_user")
def test_upload_extension_with_duplicate_guid(base_url, session_auth, variables):
"""Addon guids are unique and cannot be re-used for new addon submissions"""
guid = variables["duplicate_guid"]
# make an add-on with an already existing guid
manifest = {
**payloads.minimal_manifest,
"name": "Duplicate guid",
"browser_specific_settings": {"gecko": {"id": guid}},
}
api_helpers.make_addon(manifest)
with open("sample-addons/make-addon.zip", "rb") as file:
> upload = requests.post(
url=f"{base_url}{_upload}",
headers={"Authorization": f"Session {session_auth}"},
files={"upload": file},
data={"channel": "listed"},
)

tests/api_w/test_addon_uploads.py:435:
_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _
venv/lib/python3.11/site-packages/requests/api.py:115: in post
return request("post", url, data=data, json=json, **kwargs)
venv/lib/python3.11/site-packages/requests/api.py:59: in request
return session.request(method=method, url=url, **kwargs)
venv/lib/python3.11/site-packages/requests/sessions.py:589: in request
resp = self.send(prep, **send_kwargs)
venv/lib/python3.11/site-packages/requests/sessions.py:703: in send
r = adapter.send(request, **kwargs)
_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _

self = <requests.adapters.HTTPAdapter object at 0x103cf3c10>, request = <PreparedRequest [POST]>, stream = False, timeout = Timeout(connect=None, read=None, total=None), verify = True, cert = None
proxies = OrderedDict()

def send(
self, request, stream=False, timeout=None, verify=True, cert=None, proxies=None
):
"""Sends PreparedRequest object. Returns Response object.

:param request: The :class:`PreparedRequest <PreparedRequest>` being sent.
:param stream: (optional) Whether to stream the request content.
:param timeout: (optional) How long to wait for the server to send
data before giving up, as a float, or a :ref:`(connect timeout,
read timeout) <timeouts>` tuple.
:type timeout: float or tuple or urllib3 Timeout object
:param verify: (optional) Either a boolean, in which case it controls whether
we verify the server's TLS certificate, or a string, in which case it
must be a path to a CA bundle to use
:param cert: (optional) Any user-provided SSL certificate to be trusted.
:param proxies: (optional) The proxies dictionary to apply to the request.
:rtype: requests.Response
"""

try:
conn = self._get_connection(request, verify, proxies=proxies, cert=cert)
except LocationValueError as e:
raise InvalidURL(e, request=request)

self.cert_verify(conn, request.url, verify, cert)
url = self.request_url(request, proxies)
self.add_headers(
request,
stream=stream,
timeout=timeout,
verify=verify,
cert=cert,
proxies=proxies,
)

chunked = not (request.body is None or "Content-Length" in request.headers)

if isinstance(timeout, tuple):
try:
connect, read = timeout
timeout = TimeoutSauce(connect=connect, read=read)
except ValueError:
raise ValueError(
f"Invalid timeout {timeout}. Pass a (connect, read) timeout tuple, "
f"or a single float to set both timeouts to the same value."
)
elif isinstance(timeout, TimeoutSauce):
pass
else:
timeout = TimeoutSauce(connect=timeout, read=timeout)

try:
resp = conn.urlopen(
method=request.method,
url=url,
body=request.body,
headers=request.headers,
redirect=False,
assert_same_host=False,
preload_content=False,
decode_content=False,
retries=self.max_retries,
timeout=timeout,
chunked=chunked,
)

except (ProtocolError, OSError) as err:
raise ConnectionError(err, request=request)

except MaxRetryError as e:
if isinstance(e.reason, ConnectTimeoutError):
# TODO: Remove this in 3.0.0: see #2811
if not isinstance(e.reason, NewConnectionError):
raise ConnectTimeout(e, request=request)

if isinstance(e.reason, ResponseError):
raise RetryError(e, request=request)

if isinstance(e.reason, _ProxyError):
raise ProxyError(e, request=request)

if isinstance(e.reason, _SSLError):
# This branch is for urllib3 v1.22 and later.
raise SSLError(e, request=request)

> raise ConnectionError(e, request=request)
E requests.exceptions.ConnectionError: HTTPSConnectionPool(host='addons.allizom.org', port=443): Max retries exceeded with url: /api/v5/addons/upload/ (Caused by NameResolutionError("<urllib3.connection.HTTPSConnection object at 0x103cf3450>: Failed to resolve 'addons.allizom.org' ([Errno 8] nodename nor servname provided, or not known)"))

venv/lib/python3.11/site-packages/requests/adapters.py:597: ConnectionError
------------------------------Captured stdout call------------------------------
Manifest content: {'manifest_version': 2, 'version': '1.0', 'name': 'Duplicate guid', 'browser_specific_settings': {'gecko': {'id': '@contain-facebook'}}}
Failed tests/api_w/test_addon_uploads.py::test_upload_extension_without_name_in_manifest 0.01
self = <urllib3.connection.HTTPSConnection object at 0x103cfbfd0>

def _new_conn(self) -> socket.socket:
"""Establish a socket connection and set nodelay settings on it.

:return: New socket connection.
"""
try:
> sock = connection.create_connection(
(self._dns_host, self.port),
self.timeout,
source_address=self.source_address,
socket_options=self.socket_options,
)

venv/lib/python3.11/site-packages/urllib3/connection.py:196:
_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _
venv/lib/python3.11/site-packages/urllib3/util/connection.py:60: in create_connection
for res in socket.getaddrinfo(host, port, family, socket.SOCK_STREAM):
_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _

host = 'addons.allizom.org', port = 443, family = <AddressFamily.AF_UNSPEC: 0>, type = <SocketKind.SOCK_STREAM: 1>, proto = 0, flags = 0

def getaddrinfo(host, port, family=0, type=0, proto=0, flags=0):
"""Resolve host and port into list of address info entries.

Translate the host/port argument into a sequence of 5-tuples that contain
all the necessary arguments for creating a socket connected to that service.
host is a domain name, a string representation of an IPv4/v6 address or
None. port is a string service name such as 'http', a numeric port number or
None. By passing None as the value of host and port, you can pass NULL to
the underlying C API.

The family, type and proto arguments can be optionally specified in order to
narrow the list of addresses returned. Passing zero as a value for each of
these arguments selects the full range of results.
"""
# We override this function since we want to translate the numeric family
# and socket type values to enum constants.
addrlist = []
> for res in _socket.getaddrinfo(host, port, family, type, proto, flags):
E socket.gaierror: [Errno 8] nodename nor servname provided, or not known

/Library/Frameworks/Python.framework/Versions/3.11/lib/python3.11/socket.py:962: gaierror

The above exception was the direct cause of the following exception:

self = <urllib3.connectionpool.HTTPSConnectionPool object at 0x103cfb150>, method = 'POST', url = '/api/v5/addons/upload/'
body = b'--032661d46b78f79137249786726c12eb\r\nContent-Disposition: form-data; name="channel"\r\n\r\nlisted\r\n--032661d46b78...\x05\x06\x00\x00\x00\x00\x01\x00\x01\x00;\x00\x00\x00T\x00\x00\x00\x00\x00\r\n--032661d46b78f79137249786726c12eb--\r\n'
headers = {'User-Agent': 'python-requests/2.32.0', 'Accept-Encoding': 'gzip, deflate', 'Accept': '*/*', 'Connection': 'keep-aliv...j0yuvakt3v', 'Content-Length': '411', 'Content-Type': 'multipart/form-data; boundary=032661d46b78f79137249786726c12eb'}
retries = Retry(total=0, connect=None, read=False, redirect=None, status=None), redirect = False, assert_same_host = False, timeout = Timeout(connect=None, read=None, total=None), pool_timeout = None
release_conn = False, chunked = False, body_pos = None, preload_content = False, decode_content = False, response_kw = {}
parsed_url = Url(scheme=None, auth=None, host=None, port=None, path='/api/v5/addons/upload/', query=None, fragment=None), destination_scheme = None, conn = None, release_this_conn = True
http_tunnel_required = False, err = None, clean_exit = False

def urlopen( # type: ignore[override]
self,
method: str,
url: str,
body: _TYPE_BODY | None = None,
headers: typing.Mapping[str, str] | None = None,
retries: Retry | bool | int | None = None,
redirect: bool = True,
assert_same_host: bool = True,
timeout: _TYPE_TIMEOUT = _DEFAULT_TIMEOUT,
pool_timeout: int | None = None,
release_conn: bool | None = None,
chunked: bool = False,
body_pos: _TYPE_BODY_POSITION | None = None,
preload_content: bool = True,
decode_content: bool = True,
**response_kw: typing.Any,
) -> BaseHTTPResponse:
"""
Get a connection from the pool and perform an HTTP request. This is the
lowest level call for making a request, so you'll need to specify all
the raw details.

.. note::

More commonly, it's appropriate to use a convenience method
such as :meth:`request`.

.. note::

`release_conn` will only behave as expected if
`preload_content=False` because we want to make
`preload_content=False` the default behaviour someday soon without
breaking backwards compatibility.

:param method:
HTTP request method (such as GET, POST, PUT, etc.)

:param url:
The URL to perform the request on.

:param body:
Data to send in the request body, either :class:`str`, :class:`bytes`,
an iterable of :class:`str`/:class:`bytes`, or a file-like object.

:param headers:
Dictionary of custom headers to send, such as User-Agent,
If-None-Match, etc. If None, pool headers are used. If provided,
these headers completely replace any pool-specific headers.

:param retries:
Configure the number of retries to allow before raising a
:class:`~urllib3.exceptions.MaxRetryError` exception.

If ``None`` (default) will retry 3 times, see ``Retry.DEFAULT``. Pass a
:class:`~urllib3.util.retry.Retry` object for fine-grained control
over different types of retries.
Pass an integer number to retry connection errors that many times,
but no other types of errors. Pass zero to never retry.

If ``False``, then retries are disabled and any exception is raised
immediately. Also, instead of raising a MaxRetryError on redirects,
the redirect response will be returned.

:type retries: :class:`~urllib3.util.retry.Retry`, False, or an int.

:param redirect:
If True, automatically handle redirects (status codes 301, 302,
303, 307, 308). Each redirect counts as a retry. Disabling retries
will disable redirect, too.

:param assert_same_host:
If ``True``, will make sure that the host of the pool requests is
consistent else will raise HostChangedError. When ``False``, you can
use the pool on an HTTP proxy and request foreign hosts.

:param timeout:
If specified, overrides the default timeout for this one
request. It may be a float (in seconds) or an instance of
:class:`urllib3.util.Timeout`.

:param pool_timeout:
If set and the pool is set to block=True, then this method will
block for ``pool_timeout`` seconds and raise EmptyPoolError if no
connection is available within the time period.

:param bool preload_content:
If True, the response's body will be preloaded into memory.

:param bool decode_content:
If True, will attempt to decode the body based on the
'content-encoding' header.

:param release_conn:
If False, then the urlopen call will not release the connection
back into the pool once a response is received (but will release if
you read the entire contents of the response such as when
`preload_content=True`). This is useful if you're not preloading
the response's content immediately. You will need to call
``r.release_conn()`` on the response ``r`` to return the connection
back into the pool. If None, it takes the value of ``preload_content``
which defaults to ``True``.

:param bool chunked:
If True, urllib3 will send the body using chunked transfer
encoding. Otherwise, urllib3 will send the body using the standard
content-length form. Defaults to False.

:param int body_pos:
Position to seek to in file-like body in the event of a retry or
redirect. Typically this won't need to be set because urllib3 will
auto-populate the value when needed.
"""
parsed_url = parse_url(url)
destination_scheme = parsed_url.scheme

if headers is None:
headers = self.headers

if not isinstance(retries, Retry):
retries = Retry.from_int(retries, redirect=redirect, default=self.retries)

if release_conn is None:
release_conn = preload_content

# Check host
if assert_same_host and not self.is_same_host(url):
raise HostChangedError(self, url, retries)

# Ensure that the URL we're connecting to is properly encoded
if url.startswith("/"):
url = to_str(_encode_target(url))
else:
url = to_str(parsed_url.url)

conn = None

# Track whether `conn` needs to be released before
# returning/raising/recursing. Update this variable if necessary, and
# leave `release_conn` constant throughout the function. That way, if
# the function recurses, the original value of `release_conn` will be
# passed down into the recursive call, and its value will be respected.
#
# See issue #651 [1] for details.
#
# [1] <https://github.com/urllib3/urllib3/issues/651>
release_this_conn = release_conn

http_tunnel_required = connection_requires_http_tunnel(
self.proxy, self.proxy_config, destination_scheme
)

# Merge the proxy headers. Only done when not using HTTP CONNECT. We
# have to copy the headers dict so we can safely change it without those
# changes being reflected in anyone else's copy.
if not http_tunnel_required:
headers = headers.copy() # type: ignore[attr-defined]
headers.update(self.proxy_headers) # type: ignore[union-attr]

# Must keep the exception bound to a separate variable or else Python 3
# complains about UnboundLocalError.
err = None

# Keep track of whether we cleanly exited the except block. This
# ensures we do proper cleanup in finally.
clean_exit = False

# Rewind body position, if needed. Record current position
# for future rewinds in the event of a redirect/retry.
body_pos = set_file_position(body, body_pos)

try:
# Request a connection from the queue.
timeout_obj = self._get_timeout(timeout)
conn = self._get_conn(timeout=pool_timeout)

conn.timeout = timeout_obj.connect_timeout # type: ignore[assignment]

# Is this a closed/new connection that requires CONNECT tunnelling?
if self.proxy is not None and http_tunnel_required and conn.is_closed:
try:
self._prepare_proxy(conn)
except (BaseSSLError, OSError, SocketTimeout) as e:
self._raise_timeout(
err=e, url=self.proxy.url, timeout_value=conn.timeout
)
raise

# If we're going to release the connection in ``finally:``, then
# the response doesn't need to know about the connection. Otherwise
# it will also try to release it and we'll have a double-release
# mess.
response_conn = conn if not release_conn else None

# Make the request on the HTTPConnection object
> response = self._make_request(
conn,
method,
url,
timeout=timeout_obj,
body=body,
headers=headers,
chunked=chunked,
retries=retries,
response_conn=response_conn,
preload_content=preload_content,
decode_content=decode_content,
**response_kw,
)

venv/lib/python3.11/site-packages/urllib3/connectionpool.py:789:
_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _
venv/lib/python3.11/site-packages/urllib3/connectionpool.py:490: in _make_request
raise new_e
venv/lib/python3.11/site-packages/urllib3/connectionpool.py:466: in _make_request
self._validate_conn(conn)
venv/lib/python3.11/site-packages/urllib3/connectionpool.py:1095: in _validate_conn
conn.connect()
venv/lib/python3.11/site-packages/urllib3/connection.py:615: in connect
self.sock = sock = self._new_conn()
_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _

self = <urllib3.connection.HTTPSConnection object at 0x103cfbfd0>

def _new_conn(self) -> socket.socket:
"""Establish a socket connection and set nodelay settings on it.

:return: New socket connection.
"""
try:
sock = connection.create_connection(
(self._dns_host, self.port),
self.timeout,
source_address=self.source_address,
socket_options=self.socket_options,
)
except socket.gaierror as e:
> raise NameResolutionError(self.host, self, e) from e
E urllib3.exceptions.NameResolutionError: <urllib3.connection.HTTPSConnection object at 0x103cfbfd0>: Failed to resolve 'addons.allizom.org' ([Errno 8] nodename nor servname provided, or not known)

venv/lib/python3.11/site-packages/urllib3/connection.py:203: NameResolutionError

The above exception was the direct cause of the following exception:

self = <requests.adapters.HTTPAdapter object at 0x103cfa990>, request = <PreparedRequest [POST]>, stream = False, timeout = Timeout(connect=None, read=None, total=None), verify = True, cert = None
proxies = OrderedDict()

def send(
self, request, stream=False, timeout=None, verify=True, cert=None, proxies=None
):
"""Sends PreparedRequest object. Returns Response object.

:param request: The :class:`PreparedRequest <PreparedRequest>` being sent.
:param stream: (optional) Whether to stream the request content.
:param timeout: (optional) How long to wait for the server to send
data before giving up, as a float, or a :ref:`(connect timeout,
read timeout) <timeouts>` tuple.
:type timeout: float or tuple or urllib3 Timeout object
:param verify: (optional) Either a boolean, in which case it controls whether
we verify the server's TLS certificate, or a string, in which case it
must be a path to a CA bundle to use
:param cert: (optional) Any user-provided SSL certificate to be trusted.
:param proxies: (optional) The proxies dictionary to apply to the request.
:rtype: requests.Response
"""

try:
conn = self._get_connection(request, verify, proxies=proxies, cert=cert)
except LocationValueError as e:
raise InvalidURL(e, request=request)

self.cert_verify(conn, request.url, verify, cert)
url = self.request_url(request, proxies)
self.add_headers(
request,
stream=stream,
timeout=timeout,
verify=verify,
cert=cert,
proxies=proxies,
)

chunked = not (request.body is None or "Content-Length" in request.headers)

if isinstance(timeout, tuple):
try:
connect, read = timeout
timeout = TimeoutSauce(connect=connect, read=read)
except ValueError:
raise ValueError(
f"Invalid timeout {timeout}. Pass a (connect, read) timeout tuple, "
f"or a single float to set both timeouts to the same value."
)
elif isinstance(timeout, TimeoutSauce):
pass
else:
timeout = TimeoutSauce(connect=timeout, read=timeout)

try:
> resp = conn.urlopen(
method=request.method,
url=url,
body=request.body,
headers=request.headers,
redirect=False,
assert_same_host=False,
preload_content=False,
decode_content=False,
retries=self.max_retries,
timeout=timeout,
chunked=chunked,
)

venv/lib/python3.11/site-packages/requests/adapters.py:564:
_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _
venv/lib/python3.11/site-packages/urllib3/connectionpool.py:843: in urlopen
retries = retries.increment(
_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _

self = Retry(total=0, connect=None, read=False, redirect=None, status=None), method = 'POST', url = '/api/v5/addons/upload/', response = None
error = NameResolutionError("<urllib3.connection.HTTPSConnection object at 0x103cfbfd0>: Failed to resolve 'addons.allizom.org' ([Errno 8] nodename nor servname provided, or not known)")
_pool = <urllib3.connectionpool.HTTPSConnectionPool object at 0x103cfb150>, _stacktrace = <traceback object at 0x103cfa300>

def increment(
self,
method: str | None = None,
url: str | None = None,
response: BaseHTTPResponse | None = None,
error: Exception | None = None,
_pool: ConnectionPool | None = None,
_stacktrace: TracebackType | None = None,
) -> Self:
"""Return a new Retry object with incremented retry counters.

:param response: A response object, or None, if the server did not
return a response.
:type response: :class:`~urllib3.response.BaseHTTPResponse`
:param Exception error: An error encountered during the request, or
None if the response was received successfully.

:return: A new ``Retry`` object.
"""
if self.total is False and error:
# Disabled, indicate to re-raise the error.
raise reraise(type(error), error, _stacktrace)

total = self.total
if total is not None:
total -= 1

connect = self.connect
read = self.read
redirect = self.redirect
status_count = self.status
other = self.other
cause = "unknown"
status = None
redirect_location = None

if error and self._is_connection_error(error):
# Connect retry?
if connect is False:
raise reraise(type(error), error, _stacktrace)
elif connect is not None:
connect -= 1

elif error and self._is_read_error(error):
# Read retry?
if read is False or method is None or not self._is_method_retryable(method):
raise reraise(type(error), error, _stacktrace)
elif read is not None:
read -= 1

elif error:
# Other retry?
if other is not None:
other -= 1

elif response and response.get_redirect_location():
# Redirect retry?
if redirect is not None:
redirect -= 1
cause = "too many redirects"
response_redirect_location = response.get_redirect_location()
if response_redirect_location:
redirect_location = response_redirect_location
status = response.status

else:
# Incrementing because of a server error like a 500 in
# status_forcelist and the given method is in the allowed_methods
cause = ResponseError.GENERIC_ERROR
if response and response.status:
if status_count is not None:
status_count -= 1
cause = ResponseError.SPECIFIC_ERROR.format(status_code=response.status)
status = response.status

history = self.history + (
RequestHistory(method, url, error, status, redirect_location),
)

new_retry = self.new(
total=total,
connect=connect,
read=read,
redirect=redirect,
status=status_count,
other=other,
history=history,
)

if new_retry.is_exhausted():
reason = error or ResponseError(cause)
> raise MaxRetryError(_pool, url, reason) from reason # type: ignore[arg-type]
E urllib3.exceptions.MaxRetryError: HTTPSConnectionPool(host='addons.allizom.org', port=443): Max retries exceeded with url: /api/v5/addons/upload/ (Caused by NameResolutionError("<urllib3.connection.HTTPSConnection object at 0x103cfbfd0>: Failed to resolve 'addons.allizom.org' ([Errno 8] nodename nor servname provided, or not known)"))

venv/lib/python3.11/site-packages/urllib3/util/retry.py:519: MaxRetryError

During handling of the above exception, another exception occurred:

base_url = 'https://addons.allizom.org', session_auth = 'ldvd5ag27bkfpukx6rn2lcj0yuvakt3v'

@pytest.mark.serial
@pytest.mark.create_session("api_user")
def test_upload_extension_without_name_in_manifest(base_url, session_auth):
"""The 'name' key is mandatory for successful submissions; uploading an
addon with a manifest that misses a 'name' key should fail"""
# create a manifest that doesn't include the mandatory 'name' key
manifest = {**payloads.minimal_manifest}
api_helpers.make_addon(manifest)
with open("sample-addons/make-addon.zip", "rb") as file:
> upload = requests.post(
url=f"{base_url}{_upload}",
headers={"Authorization": f"Session {session_auth}"},
files={"upload": file},
data={"channel": "listed"},
)

tests/api_w/test_addon_uploads.py:472:
_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _
venv/lib/python3.11/site-packages/requests/api.py:115: in post
return request("post", url, data=data, json=json, **kwargs)
venv/lib/python3.11/site-packages/requests/api.py:59: in request
return session.request(method=method, url=url, **kwargs)
venv/lib/python3.11/site-packages/requests/sessions.py:589: in request
resp = self.send(prep, **send_kwargs)
venv/lib/python3.11/site-packages/requests/sessions.py:703: in send
r = adapter.send(request, **kwargs)
_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _

self = <requests.adapters.HTTPAdapter object at 0x103cfa990>, request = <PreparedRequest [POST]>, stream = False, timeout = Timeout(connect=None, read=None, total=None), verify = True, cert = None
proxies = OrderedDict()

def send(
self, request, stream=False, timeout=None, verify=True, cert=None, proxies=None
):
"""Sends PreparedRequest object. Returns Response object.

:param request: The :class:`PreparedRequest <PreparedRequest>` being sent.
:param stream: (optional) Whether to stream the request content.
:param timeout: (optional) How long to wait for the server to send
data before giving up, as a float, or a :ref:`(connect timeout,
read timeout) <timeouts>` tuple.
:type timeout: float or tuple or urllib3 Timeout object
:param verify: (optional) Either a boolean, in which case it controls whether
we verify the server's TLS certificate, or a string, in which case it
must be a path to a CA bundle to use
:param cert: (optional) Any user-provided SSL certificate to be trusted.
:param proxies: (optional) The proxies dictionary to apply to the request.
:rtype: requests.Response
"""

try:
conn = self._get_connection(request, verify, proxies=proxies, cert=cert)
except LocationValueError as e:
raise InvalidURL(e, request=request)

self.cert_verify(conn, request.url, verify, cert)
url = self.request_url(request, proxies)
self.add_headers(
request,
stream=stream,
timeout=timeout,
verify=verify,
cert=cert,
proxies=proxies,
)

chunked = not (request.body is None or "Content-Length" in request.headers)

if isinstance(timeout, tuple):
try:
connect, read = timeout
timeout = TimeoutSauce(connect=connect, read=read)
except ValueError:
raise ValueError(
f"Invalid timeout {timeout}. Pass a (connect, read) timeout tuple, "
f"or a single float to set both timeouts to the same value."
)
elif isinstance(timeout, TimeoutSauce):
pass
else:
timeout = TimeoutSauce(connect=timeout, read=timeout)

try:
resp = conn.urlopen(
method=request.method,
url=url,
body=request.body,
headers=request.headers,
redirect=False,
assert_same_host=False,
preload_content=False,
decode_content=False,
retries=self.max_retries,
timeout=timeout,
chunked=chunked,
)

except (ProtocolError, OSError) as err:
raise ConnectionError(err, request=request)

except MaxRetryError as e:
if isinstance(e.reason, ConnectTimeoutError):
# TODO: Remove this in 3.0.0: see #2811
if not isinstance(e.reason, NewConnectionError):
raise ConnectTimeout(e, request=request)

if isinstance(e.reason, ResponseError):
raise RetryError(e, request=request)

if isinstance(e.reason, _ProxyError):
raise ProxyError(e, request=request)

if isinstance(e.reason, _SSLError):
# This branch is for urllib3 v1.22 and later.
raise SSLError(e, request=request)

> raise ConnectionError(e, request=request)
E requests.exceptions.ConnectionError: HTTPSConnectionPool(host='addons.allizom.org', port=443): Max retries exceeded with url: /api/v5/addons/upload/ (Caused by NameResolutionError("<urllib3.connection.HTTPSConnection object at 0x103cfbfd0>: Failed to resolve 'addons.allizom.org' ([Errno 8] nodename nor servname provided, or not known)"))

venv/lib/python3.11/site-packages/requests/adapters.py:597: ConnectionError
------------------------------Captured stdout call------------------------------
Manifest content: {'manifest_version': 2, 'version': '1.0'}
Failed tests/api_w/test_addon_uploads.py::test_upload_extension_without_summary 0.01
self = <urllib3.connection.HTTPSConnection object at 0x103b84790>

def _new_conn(self) -> socket.socket:
"""Establish a socket connection and set nodelay settings on it.

:return: New socket connection.
"""
try:
> sock = connection.create_connection(
(self._dns_host, self.port),
self.timeout,
source_address=self.source_address,
socket_options=self.socket_options,
)

venv/lib/python3.11/site-packages/urllib3/connection.py:196:
_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _
venv/lib/python3.11/site-packages/urllib3/util/connection.py:60: in create_connection
for res in socket.getaddrinfo(host, port, family, socket.SOCK_STREAM):
_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _

host = 'addons.allizom.org', port = 443, family = <AddressFamily.AF_UNSPEC: 0>, type = <SocketKind.SOCK_STREAM: 1>, proto = 0, flags = 0

def getaddrinfo(host, port, family=0, type=0, proto=0, flags=0):
"""Resolve host and port into list of address info entries.

Translate the host/port argument into a sequence of 5-tuples that contain
all the necessary arguments for creating a socket connected to that service.
host is a domain name, a string representation of an IPv4/v6 address or
None. port is a string service name such as 'http', a numeric port number or
None. By passing None as the value of host and port, you can pass NULL to
the underlying C API.

The family, type and proto arguments can be optionally specified in order to
narrow the list of addresses returned. Passing zero as a value for each of
these arguments selects the full range of results.
"""
# We override this function since we want to translate the numeric family
# and socket type values to enum constants.
addrlist = []
> for res in _socket.getaddrinfo(host, port, family, type, proto, flags):
E socket.gaierror: [Errno 8] nodename nor servname provided, or not known

/Library/Frameworks/Python.framework/Versions/3.11/lib/python3.11/socket.py:962: gaierror

The above exception was the direct cause of the following exception:

self = <urllib3.connectionpool.HTTPSConnectionPool object at 0x103b84290>, method = 'POST', url = '/api/v5/addons/upload/'
body = b'--5ac382ff8070b0114a528293f08ffbe2\r\nContent-Disposition: form-data; name="channel"\r\n\r\nlisted\r\n--5ac382ff8070...\x05\x06\x00\x00\x00\x00\x01\x00\x01\x00;\x00\x00\x00u\x00\x00\x00\x00\x00\r\n--5ac382ff8070b0114a528293f08ffbe2--\r\n'
headers = {'User-Agent': 'python-requests/2.32.0', 'Accept-Encoding': 'gzip, deflate', 'Accept': '*/*', 'Connection': 'keep-aliv...j0yuvakt3v', 'Content-Length': '444', 'Content-Type': 'multipart/form-data; boundary=5ac382ff8070b0114a528293f08ffbe2'}
retries = Retry(total=0, connect=None, read=False, redirect=None, status=None), redirect = False, assert_same_host = False, timeout = Timeout(connect=None, read=None, total=None), pool_timeout = None
release_conn = False, chunked = False, body_pos = None, preload_content = False, decode_content = False, response_kw = {}
parsed_url = Url(scheme=None, auth=None, host=None, port=None, path='/api/v5/addons/upload/', query=None, fragment=None), destination_scheme = None, conn = None, release_this_conn = True
http_tunnel_required = False, err = None, clean_exit = False

def urlopen( # type: ignore[override]
self,
method: str,
url: str,
body: _TYPE_BODY | None = None,
headers: typing.Mapping[str, str] | None = None,
retries: Retry | bool | int | None = None,
redirect: bool = True,
assert_same_host: bool = True,
timeout: _TYPE_TIMEOUT = _DEFAULT_TIMEOUT,
pool_timeout: int | None = None,
release_conn: bool | None = None,
chunked: bool = False,
body_pos: _TYPE_BODY_POSITION | None = None,
preload_content: bool = True,
decode_content: bool = True,
**response_kw: typing.Any,
) -> BaseHTTPResponse:
"""
Get a connection from the pool and perform an HTTP request. This is the
lowest level call for making a request, so you'll need to specify all
the raw details.

.. note::

More commonly, it's appropriate to use a convenience method
such as :meth:`request`.

.. note::

`release_conn` will only behave as expected if
`preload_content=False` because we want to make
`preload_content=False` the default behaviour someday soon without
breaking backwards compatibility.

:param method:
HTTP request method (such as GET, POST, PUT, etc.)

:param url:
The URL to perform the request on.

:param body:
Data to send in the request body, either :class:`str`, :class:`bytes`,
an iterable of :class:`str`/:class:`bytes`, or a file-like object.

:param headers:
Dictionary of custom headers to send, such as User-Agent,
If-None-Match, etc. If None, pool headers are used. If provided,
these headers completely replace any pool-specific headers.

:param retries:
Configure the number of retries to allow before raising a
:class:`~urllib3.exceptions.MaxRetryError` exception.

If ``None`` (default) will retry 3 times, see ``Retry.DEFAULT``. Pass a
:class:`~urllib3.util.retry.Retry` object for fine-grained control
over different types of retries.
Pass an integer number to retry connection errors that many times,
but no other types of errors. Pass zero to never retry.

If ``False``, then retries are disabled and any exception is raised
immediately. Also, instead of raising a MaxRetryError on redirects,
the redirect response will be returned.

:type retries: :class:`~urllib3.util.retry.Retry`, False, or an int.

:param redirect:
If True, automatically handle redirects (status codes 301, 302,
303, 307, 308). Each redirect counts as a retry. Disabling retries
will disable redirect, too.

:param assert_same_host:
If ``True``, will make sure that the host of the pool requests is
consistent else will raise HostChangedError. When ``False``, you can
use the pool on an HTTP proxy and request foreign hosts.

:param timeout:
If specified, overrides the default timeout for this one
request. It may be a float (in seconds) or an instance of
:class:`urllib3.util.Timeout`.

:param pool_timeout:
If set and the pool is set to block=True, then this method will
block for ``pool_timeout`` seconds and raise EmptyPoolError if no
connection is available within the time period.

:param bool preload_content:
If True, the response's body will be preloaded into memory.

:param bool decode_content:
If True, will attempt to decode the body based on the
'content-encoding' header.

:param release_conn:
If False, then the urlopen call will not release the connection
back into the pool once a response is received (but will release if
you read the entire contents of the response such as when
`preload_content=True`). This is useful if you're not preloading
the response's content immediately. You will need to call
``r.release_conn()`` on the response ``r`` to return the connection
back into the pool. If None, it takes the value of ``preload_content``
which defaults to ``True``.

:param bool chunked:
If True, urllib3 will send the body using chunked transfer
encoding. Otherwise, urllib3 will send the body using the standard
content-length form. Defaults to False.

:param int body_pos:
Position to seek to in file-like body in the event of a retry or
redirect. Typically this won't need to be set because urllib3 will
auto-populate the value when needed.
"""
parsed_url = parse_url(url)
destination_scheme = parsed_url.scheme

if headers is None:
headers = self.headers

if not isinstance(retries, Retry):
retries = Retry.from_int(retries, redirect=redirect, default=self.retries)

if release_conn is None:
release_conn = preload_content

# Check host
if assert_same_host and not self.is_same_host(url):
raise HostChangedError(self, url, retries)

# Ensure that the URL we're connecting to is properly encoded
if url.startswith("/"):
url = to_str(_encode_target(url))
else:
url = to_str(parsed_url.url)

conn = None

# Track whether `conn` needs to be released before
# returning/raising/recursing. Update this variable if necessary, and
# leave `release_conn` constant throughout the function. That way, if
# the function recurses, the original value of `release_conn` will be
# passed down into the recursive call, and its value will be respected.
#
# See issue #651 [1] for details.
#
# [1] <https://github.com/urllib3/urllib3/issues/651>
release_this_conn = release_conn

http_tunnel_required = connection_requires_http_tunnel(
self.proxy, self.proxy_config, destination_scheme
)

# Merge the proxy headers. Only done when not using HTTP CONNECT. We
# have to copy the headers dict so we can safely change it without those
# changes being reflected in anyone else's copy.
if not http_tunnel_required:
headers = headers.copy() # type: ignore[attr-defined]
headers.update(self.proxy_headers) # type: ignore[union-attr]

# Must keep the exception bound to a separate variable or else Python 3
# complains about UnboundLocalError.
err = None

# Keep track of whether we cleanly exited the except block. This
# ensures we do proper cleanup in finally.
clean_exit = False

# Rewind body position, if needed. Record current position
# for future rewinds in the event of a redirect/retry.
body_pos = set_file_position(body, body_pos)

try:
# Request a connection from the queue.
timeout_obj = self._get_timeout(timeout)
conn = self._get_conn(timeout=pool_timeout)

conn.timeout = timeout_obj.connect_timeout # type: ignore[assignment]

# Is this a closed/new connection that requires CONNECT tunnelling?
if self.proxy is not None and http_tunnel_required and conn.is_closed:
try:
self._prepare_proxy(conn)
except (BaseSSLError, OSError, SocketTimeout) as e:
self._raise_timeout(
err=e, url=self.proxy.url, timeout_value=conn.timeout
)
raise

# If we're going to release the connection in ``finally:``, then
# the response doesn't need to know about the connection. Otherwise
# it will also try to release it and we'll have a double-release
# mess.
response_conn = conn if not release_conn else None

# Make the request on the HTTPConnection object
> response = self._make_request(
conn,
method,
url,
timeout=timeout_obj,
body=body,
headers=headers,
chunked=chunked,
retries=retries,
response_conn=response_conn,
preload_content=preload_content,
decode_content=decode_content,
**response_kw,
)

venv/lib/python3.11/site-packages/urllib3/connectionpool.py:789:
_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _
venv/lib/python3.11/site-packages/urllib3/connectionpool.py:490: in _make_request
raise new_e
venv/lib/python3.11/site-packages/urllib3/connectionpool.py:466: in _make_request
self._validate_conn(conn)
venv/lib/python3.11/site-packages/urllib3/connectionpool.py:1095: in _validate_conn
conn.connect()
venv/lib/python3.11/site-packages/urllib3/connection.py:615: in connect
self.sock = sock = self._new_conn()
_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _

self = <urllib3.connection.HTTPSConnection object at 0x103b84790>

def _new_conn(self) -> socket.socket:
"""Establish a socket connection and set nodelay settings on it.

:return: New socket connection.
"""
try:
sock = connection.create_connection(
(self._dns_host, self.port),
self.timeout,
source_address=self.source_address,
socket_options=self.socket_options,
)
except socket.gaierror as e:
> raise NameResolutionError(self.host, self, e) from e
E urllib3.exceptions.NameResolutionError: <urllib3.connection.HTTPSConnection object at 0x103b84790>: Failed to resolve 'addons.allizom.org' ([Errno 8] nodename nor servname provided, or not known)

venv/lib/python3.11/site-packages/urllib3/connection.py:203: NameResolutionError

The above exception was the direct cause of the following exception:

self = <requests.adapters.HTTPAdapter object at 0x103b86990>, request = <PreparedRequest [POST]>, stream = False, timeout = Timeout(connect=None, read=None, total=None), verify = True, cert = None
proxies = OrderedDict()

def send(
self, request, stream=False, timeout=None, verify=True, cert=None, proxies=None
):
"""Sends PreparedRequest object. Returns Response object.

:param request: The :class:`PreparedRequest <PreparedRequest>` being sent.
:param stream: (optional) Whether to stream the request content.
:param timeout: (optional) How long to wait for the server to send
data before giving up, as a float, or a :ref:`(connect timeout,
read timeout) <timeouts>` tuple.
:type timeout: float or tuple or urllib3 Timeout object
:param verify: (optional) Either a boolean, in which case it controls whether
we verify the server's TLS certificate, or a string, in which case it
must be a path to a CA bundle to use
:param cert: (optional) Any user-provided SSL certificate to be trusted.
:param proxies: (optional) The proxies dictionary to apply to the request.
:rtype: requests.Response
"""

try:
conn = self._get_connection(request, verify, proxies=proxies, cert=cert)
except LocationValueError as e:
raise InvalidURL(e, request=request)

self.cert_verify(conn, request.url, verify, cert)
url = self.request_url(request, proxies)
self.add_headers(
request,
stream=stream,
timeout=timeout,
verify=verify,
cert=cert,
proxies=proxies,
)

chunked = not (request.body is None or "Content-Length" in request.headers)

if isinstance(timeout, tuple):
try:
connect, read = timeout
timeout = TimeoutSauce(connect=connect, read=read)
except ValueError:
raise ValueError(
f"Invalid timeout {timeout}. Pass a (connect, read) timeout tuple, "
f"or a single float to set both timeouts to the same value."
)
elif isinstance(timeout, TimeoutSauce):
pass
else:
timeout = TimeoutSauce(connect=timeout, read=timeout)

try:
> resp = conn.urlopen(
method=request.method,
url=url,
body=request.body,
headers=request.headers,
redirect=False,
assert_same_host=False,
preload_content=False,
decode_content=False,
retries=self.max_retries,
timeout=timeout,
chunked=chunked,
)

venv/lib/python3.11/site-packages/requests/adapters.py:564:
_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _
venv/lib/python3.11/site-packages/urllib3/connectionpool.py:843: in urlopen
retries = retries.increment(
_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _

self = Retry(total=0, connect=None, read=False, redirect=None, status=None), method = 'POST', url = '/api/v5/addons/upload/', response = None
error = NameResolutionError("<urllib3.connection.HTTPSConnection object at 0x103b84790>: Failed to resolve 'addons.allizom.org' ([Errno 8] nodename nor servname provided, or not known)")
_pool = <urllib3.connectionpool.HTTPSConnectionPool object at 0x103b84290>, _stacktrace = <traceback object at 0x103b84580>

def increment(
self,
method: str | None = None,
url: str | None = None,
response: BaseHTTPResponse | None = None,
error: Exception | None = None,
_pool: ConnectionPool | None = None,
_stacktrace: TracebackType | None = None,
) -> Self:
"""Return a new Retry object with incremented retry counters.

:param response: A response object, or None, if the server did not
return a response.
:type response: :class:`~urllib3.response.BaseHTTPResponse`
:param Exception error: An error encountered during the request, or
None if the response was received successfully.

:return: A new ``Retry`` object.
"""
if self.total is False and error:
# Disabled, indicate to re-raise the error.
raise reraise(type(error), error, _stacktrace)

total = self.total
if total is not None:
total -= 1

connect = self.connect
read = self.read
redirect = self.redirect
status_count = self.status
other = self.other
cause = "unknown"
status = None
redirect_location = None

if error and self._is_connection_error(error):
# Connect retry?
if connect is False:
raise reraise(type(error), error, _stacktrace)
elif connect is not None:
connect -= 1

elif error and self._is_read_error(error):
# Read retry?
if read is False or method is None or not self._is_method_retryable(method):
raise reraise(type(error), error, _stacktrace)
elif read is not None:
read -= 1

elif error:
# Other retry?
if other is not None:
other -= 1

elif response and response.get_redirect_location():
# Redirect retry?
if redirect is not None:
redirect -= 1
cause = "too many redirects"
response_redirect_location = response.get_redirect_location()
if response_redirect_location:
redirect_location = response_redirect_location
status = response.status

else:
# Incrementing because of a server error like a 500 in
# status_forcelist and the given method is in the allowed_methods
cause = ResponseError.GENERIC_ERROR
if response and response.status:
if status_count is not None:
status_count -= 1
cause = ResponseError.SPECIFIC_ERROR.format(status_code=response.status)
status = response.status

history = self.history + (
RequestHistory(method, url, error, status, redirect_location),
)

new_retry = self.new(
total=total,
connect=connect,
read=read,
redirect=redirect,
status=status_count,
other=other,
history=history,
)

if new_retry.is_exhausted():
reason = error or ResponseError(cause)
> raise MaxRetryError(_pool, url, reason) from reason # type: ignore[arg-type]
E urllib3.exceptions.MaxRetryError: HTTPSConnectionPool(host='addons.allizom.org', port=443): Max retries exceeded with url: /api/v5/addons/upload/ (Caused by NameResolutionError("<urllib3.connection.HTTPSConnection object at 0x103b84790>: Failed to resolve 'addons.allizom.org' ([Errno 8] nodename nor servname provided, or not known)"))

venv/lib/python3.11/site-packages/urllib3/util/retry.py:519: MaxRetryError

During handling of the above exception, another exception occurred:

base_url = 'https://addons.allizom.org', session_auth = 'ldvd5ag27bkfpukx6rn2lcj0yuvakt3v'

@pytest.mark.serial
@pytest.mark.create_session("api_user")
def test_upload_extension_without_summary(base_url, session_auth):
"""An addon summary is mandatory for successful submissions; uploading an addon without a
'description' key and no 'summary' included in the JSON payload should fail"""
# create a minimal manifest, without adding a 'description' field
manifest = {**payloads.minimal_manifest, "name": "Addon without Summary"}
api_helpers.make_addon(manifest)
with open("sample-addons/make-addon.zip", "rb") as file:
> upload = requests.post(
url=f"{base_url}{_upload}",
headers={"Authorization": f"Session {session_auth}"},
files={"upload": file},
data={"channel": "listed"},
)

tests/api_w/test_addon_uploads.py:520:
_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _
venv/lib/python3.11/site-packages/requests/api.py:115: in post
return request("post", url, data=data, json=json, **kwargs)
venv/lib/python3.11/site-packages/requests/api.py:59: in request
return session.request(method=method, url=url, **kwargs)
venv/lib/python3.11/site-packages/requests/sessions.py:589: in request
resp = self.send(prep, **send_kwargs)
venv/lib/python3.11/site-packages/requests/sessions.py:703: in send
r = adapter.send(request, **kwargs)
_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _

self = <requests.adapters.HTTPAdapter object at 0x103b86990>, request = <PreparedRequest [POST]>, stream = False, timeout = Timeout(connect=None, read=None, total=None), verify = True, cert = None
proxies = OrderedDict()

def send(
self, request, stream=False, timeout=None, verify=True, cert=None, proxies=None
):
"""Sends PreparedRequest object. Returns Response object.

:param request: The :class:`PreparedRequest <PreparedRequest>` being sent.
:param stream: (optional) Whether to stream the request content.
:param timeout: (optional) How long to wait for the server to send
data before giving up, as a float, or a :ref:`(connect timeout,
read timeout) <timeouts>` tuple.
:type timeout: float or tuple or urllib3 Timeout object
:param verify: (optional) Either a boolean, in which case it controls whether
we verify the server's TLS certificate, or a string, in which case it
must be a path to a CA bundle to use
:param cert: (optional) Any user-provided SSL certificate to be trusted.
:param proxies: (optional) The proxies dictionary to apply to the request.
:rtype: requests.Response
"""

try:
conn = self._get_connection(request, verify, proxies=proxies, cert=cert)
except LocationValueError as e:
raise InvalidURL(e, request=request)

self.cert_verify(conn, request.url, verify, cert)
url = self.request_url(request, proxies)
self.add_headers(
request,
stream=stream,
timeout=timeout,
verify=verify,
cert=cert,
proxies=proxies,
)

chunked = not (request.body is None or "Content-Length" in request.headers)

if isinstance(timeout, tuple):
try:
connect, read = timeout
timeout = TimeoutSauce(connect=connect, read=read)
except ValueError:
raise ValueError(
f"Invalid timeout {timeout}. Pass a (connect, read) timeout tuple, "
f"or a single float to set both timeouts to the same value."
)
elif isinstance(timeout, TimeoutSauce):
pass
else:
timeout = TimeoutSauce(connect=timeout, read=timeout)

try:
resp = conn.urlopen(
method=request.method,
url=url,
body=request.body,
headers=request.headers,
redirect=False,
assert_same_host=False,
preload_content=False,
decode_content=False,
retries=self.max_retries,
timeout=timeout,
chunked=chunked,
)

except (ProtocolError, OSError) as err:
raise ConnectionError(err, request=request)

except MaxRetryError as e:
if isinstance(e.reason, ConnectTimeoutError):
# TODO: Remove this in 3.0.0: see #2811
if not isinstance(e.reason, NewConnectionError):
raise ConnectTimeout(e, request=request)

if isinstance(e.reason, ResponseError):
raise RetryError(e, request=request)

if isinstance(e.reason, _ProxyError):
raise ProxyError(e, request=request)

if isinstance(e.reason, _SSLError):
# This branch is for urllib3 v1.22 and later.
raise SSLError(e, request=request)

> raise ConnectionError(e, request=request)
E requests.exceptions.ConnectionError: HTTPSConnectionPool(host='addons.allizom.org', port=443): Max retries exceeded with url: /api/v5/addons/upload/ (Caused by NameResolutionError("<urllib3.connection.HTTPSConnection object at 0x103b84790>: Failed to resolve 'addons.allizom.org' ([Errno 8] nodename nor servname provided, or not known)"))

venv/lib/python3.11/site-packages/requests/adapters.py:597: ConnectionError
------------------------------Captured stdout call------------------------------
Manifest content: {'manifest_version': 2, 'version': '1.0', 'name': 'Addon without Summary'}
Failed tests/api_w/test_addon_uploads.py::test_upload_extension_with_incorrect_version_number 0.03
self = <urllib3.connection.HTTPSConnection object at 0x103ddc3d0>

def _new_conn(self) -> socket.socket:
"""Establish a socket connection and set nodelay settings on it.

:return: New socket connection.
"""
try:
> sock = connection.create_connection(
(self._dns_host, self.port),
self.timeout,
source_address=self.source_address,
socket_options=self.socket_options,
)

venv/lib/python3.11/site-packages/urllib3/connection.py:196:
_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _
venv/lib/python3.11/site-packages/urllib3/util/connection.py:60: in create_connection
for res in socket.getaddrinfo(host, port, family, socket.SOCK_STREAM):
_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _

host = 'addons.allizom.org', port = 443, family = <AddressFamily.AF_UNSPEC: 0>, type = <SocketKind.SOCK_STREAM: 1>, proto = 0, flags = 0

def getaddrinfo(host, port, family=0, type=0, proto=0, flags=0):
"""Resolve host and port into list of address info entries.

Translate the host/port argument into a sequence of 5-tuples that contain
all the necessary arguments for creating a socket connected to that service.
host is a domain name, a string representation of an IPv4/v6 address or
None. port is a string service name such as 'http', a numeric port number or
None. By passing None as the value of host and port, you can pass NULL to
the underlying C API.

The family, type and proto arguments can be optionally specified in order to
narrow the list of addresses returned. Passing zero as a value for each of
these arguments selects the full range of results.
"""
# We override this function since we want to translate the numeric family
# and socket type values to enum constants.
addrlist = []
> for res in _socket.getaddrinfo(host, port, family, type, proto, flags):
E socket.gaierror: [Errno 8] nodename nor servname provided, or not known

/Library/Frameworks/Python.framework/Versions/3.11/lib/python3.11/socket.py:962: gaierror

The above exception was the direct cause of the following exception:

self = <urllib3.connectionpool.HTTPSConnectionPool object at 0x103ddd790>, method = 'POST', url = '/api/v5/addons/upload/'
body = b'--096071fb1f7d62529a3325802ebb7074\r\nContent-Disposition: form-data; name="channel"\r\n\r\nlisted\r\n--096071fb1f7d...5\x06\x00\x00\x00\x00\x01\x00\x01\x00;\x00\x00\x00\x82\x00\x00\x00\x00\x00\r\n--096071fb1f7d62529a3325802ebb7074--\r\n'
headers = {'User-Agent': 'python-requests/2.32.0', 'Accept-Encoding': 'gzip, deflate', 'Accept': '*/*', 'Connection': 'keep-aliv...j0yuvakt3v', 'Content-Length': '457', 'Content-Type': 'multipart/form-data; boundary=096071fb1f7d62529a3325802ebb7074'}
retries = Retry(total=0, connect=None, read=False, redirect=None, status=None), redirect = False, assert_same_host = False, timeout = Timeout(connect=None, read=None, total=None), pool_timeout = None
release_conn = False, chunked = False, body_pos = None, preload_content = False, decode_content = False, response_kw = {}
parsed_url = Url(scheme=None, auth=None, host=None, port=None, path='/api/v5/addons/upload/', query=None, fragment=None), destination_scheme = None, conn = None, release_this_conn = True
http_tunnel_required = False, err = None, clean_exit = False

def urlopen( # type: ignore[override]
self,
method: str,
url: str,
body: _TYPE_BODY | None = None,
headers: typing.Mapping[str, str] | None = None,
retries: Retry | bool | int | None = None,
redirect: bool = True,
assert_same_host: bool = True,
timeout: _TYPE_TIMEOUT = _DEFAULT_TIMEOUT,
pool_timeout: int | None = None,
release_conn: bool | None = None,
chunked: bool = False,
body_pos: _TYPE_BODY_POSITION | None = None,
preload_content: bool = True,
decode_content: bool = True,
**response_kw: typing.Any,
) -> BaseHTTPResponse:
"""
Get a connection from the pool and perform an HTTP request. This is the
lowest level call for making a request, so you'll need to specify all
the raw details.

.. note::

More commonly, it's appropriate to use a convenience method
such as :meth:`request`.

.. note::

`release_conn` will only behave as expected if
`preload_content=False` because we want to make
`preload_content=False` the default behaviour someday soon without
breaking backwards compatibility.

:param method:
HTTP request method (such as GET, POST, PUT, etc.)

:param url:
The URL to perform the request on.

:param body:
Data to send in the request body, either :class:`str`, :class:`bytes`,
an iterable of :class:`str`/:class:`bytes`, or a file-like object.

:param headers:
Dictionary of custom headers to send, such as User-Agent,
If-None-Match, etc. If None, pool headers are used. If provided,
these headers completely replace any pool-specific headers.

:param retries:
Configure the number of retries to allow before raising a
:class:`~urllib3.exceptions.MaxRetryError` exception.

If ``None`` (default) will retry 3 times, see ``Retry.DEFAULT``. Pass a
:class:`~urllib3.util.retry.Retry` object for fine-grained control
over different types of retries.
Pass an integer number to retry connection errors that many times,
but no other types of errors. Pass zero to never retry.

If ``False``, then retries are disabled and any exception is raised
immediately. Also, instead of raising a MaxRetryError on redirects,
the redirect response will be returned.

:type retries: :class:`~urllib3.util.retry.Retry`, False, or an int.

:param redirect:
If True, automatically handle redirects (status codes 301, 302,
303, 307, 308). Each redirect counts as a retry. Disabling retries
will disable redirect, too.

:param assert_same_host:
If ``True``, will make sure that the host of the pool requests is
consistent else will raise HostChangedError. When ``False``, you can
use the pool on an HTTP proxy and request foreign hosts.

:param timeout:
If specified, overrides the default timeout for this one
request. It may be a float (in seconds) or an instance of
:class:`urllib3.util.Timeout`.

:param pool_timeout:
If set and the pool is set to block=True, then this method will
block for ``pool_timeout`` seconds and raise EmptyPoolError if no
connection is available within the time period.

:param bool preload_content:
If True, the response's body will be preloaded into memory.

:param bool decode_content:
If True, will attempt to decode the body based on the
'content-encoding' header.

:param release_conn:
If False, then the urlopen call will not release the connection
back into the pool once a response is received (but will release if
you read the entire contents of the response such as when
`preload_content=True`). This is useful if you're not preloading
the response's content immediately. You will need to call
``r.release_conn()`` on the response ``r`` to return the connection
back into the pool. If None, it takes the value of ``preload_content``
which defaults to ``True``.

:param bool chunked:
If True, urllib3 will send the body using chunked transfer
encoding. Otherwise, urllib3 will send the body using the standard
content-length form. Defaults to False.

:param int body_pos:
Position to seek to in file-like body in the event of a retry or
redirect. Typically this won't need to be set because urllib3 will
auto-populate the value when needed.
"""
parsed_url = parse_url(url)
destination_scheme = parsed_url.scheme

if headers is None:
headers = self.headers

if not isinstance(retries, Retry):
retries = Retry.from_int(retries, redirect=redirect, default=self.retries)

if release_conn is None:
release_conn = preload_content

# Check host
if assert_same_host and not self.is_same_host(url):
raise HostChangedError(self, url, retries)

# Ensure that the URL we're connecting to is properly encoded
if url.startswith("/"):
url = to_str(_encode_target(url))
else:
url = to_str(parsed_url.url)

conn = None

# Track whether `conn` needs to be released before
# returning/raising/recursing. Update this variable if necessary, and
# leave `release_conn` constant throughout the function. That way, if
# the function recurses, the original value of `release_conn` will be
# passed down into the recursive call, and its value will be respected.
#
# See issue #651 [1] for details.
#
# [1] <https://github.com/urllib3/urllib3/issues/651>
release_this_conn = release_conn

http_tunnel_required = connection_requires_http_tunnel(
self.proxy, self.proxy_config, destination_scheme
)

# Merge the proxy headers. Only done when not using HTTP CONNECT. We
# have to copy the headers dict so we can safely change it without those
# changes being reflected in anyone else's copy.
if not http_tunnel_required:
headers = headers.copy() # type: ignore[attr-defined]
headers.update(self.proxy_headers) # type: ignore[union-attr]

# Must keep the exception bound to a separate variable or else Python 3
# complains about UnboundLocalError.
err = None

# Keep track of whether we cleanly exited the except block. This
# ensures we do proper cleanup in finally.
clean_exit = False

# Rewind body position, if needed. Record current position
# for future rewinds in the event of a redirect/retry.
body_pos = set_file_position(body, body_pos)

try:
# Request a connection from the queue.
timeout_obj = self._get_timeout(timeout)
conn = self._get_conn(timeout=pool_timeout)

conn.timeout = timeout_obj.connect_timeout # type: ignore[assignment]

# Is this a closed/new connection that requires CONNECT tunnelling?
if self.proxy is not None and http_tunnel_required and conn.is_closed:
try:
self._prepare_proxy(conn)
except (BaseSSLError, OSError, SocketTimeout) as e:
self._raise_timeout(
err=e, url=self.proxy.url, timeout_value=conn.timeout
)
raise

# If we're going to release the connection in ``finally:``, then
# the response doesn't need to know about the connection. Otherwise
# it will also try to release it and we'll have a double-release
# mess.
response_conn = conn if not release_conn else None

# Make the request on the HTTPConnection object
> response = self._make_request(
conn,
method,
url,
timeout=timeout_obj,
body=body,
headers=headers,
chunked=chunked,
retries=retries,
response_conn=response_conn,
preload_content=preload_content,
decode_content=decode_content,
**response_kw,
)

venv/lib/python3.11/site-packages/urllib3/connectionpool.py:789:
_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _
venv/lib/python3.11/site-packages/urllib3/connectionpool.py:490: in _make_request
raise new_e
venv/lib/python3.11/site-packages/urllib3/connectionpool.py:466: in _make_request
self._validate_conn(conn)
venv/lib/python3.11/site-packages/urllib3/connectionpool.py:1095: in _validate_conn
conn.connect()
venv/lib/python3.11/site-packages/urllib3/connection.py:615: in connect
self.sock = sock = self._new_conn()
_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _

self = <urllib3.connection.HTTPSConnection object at 0x103ddc3d0>

def _new_conn(self) -> socket.socket:
"""Establish a socket connection and set nodelay settings on it.

:return: New socket connection.
"""
try:
sock = connection.create_connection(
(self._dns_host, self.port),
self.timeout,
source_address=self.source_address,
socket_options=self.socket_options,
)
except socket.gaierror as e:
> raise NameResolutionError(self.host, self, e) from e
E urllib3.exceptions.NameResolutionError: <urllib3.connection.HTTPSConnection object at 0x103ddc3d0>: Failed to resolve 'addons.allizom.org' ([Errno 8] nodename nor servname provided, or not known)

venv/lib/python3.11/site-packages/urllib3/connection.py:203: NameResolutionError

The above exception was the direct cause of the following exception:

self = <requests.adapters.HTTPAdapter object at 0x103ddf350>, request = <PreparedRequest [POST]>, stream = False, timeout = Timeout(connect=None, read=None, total=None), verify = True, cert = None
proxies = OrderedDict()

def send(
self, request, stream=False, timeout=None, verify=True, cert=None, proxies=None
):
"""Sends PreparedRequest object. Returns Response object.

:param request: The :class:`PreparedRequest <PreparedRequest>` being sent.
:param stream: (optional) Whether to stream the request content.
:param timeout: (optional) How long to wait for the server to send
data before giving up, as a float, or a :ref:`(connect timeout,
read timeout) <timeouts>` tuple.
:type timeout: float or tuple or urllib3 Timeout object
:param verify: (optional) Either a boolean, in which case it controls whether
we verify the server's TLS certificate, or a string, in which case it
must be a path to a CA bundle to use
:param cert: (optional) Any user-provided SSL certificate to be trusted.
:param proxies: (optional) The proxies dictionary to apply to the request.
:rtype: requests.Response
"""

try:
conn = self._get_connection(request, verify, proxies=proxies, cert=cert)
except LocationValueError as e:
raise InvalidURL(e, request=request)

self.cert_verify(conn, request.url, verify, cert)
url = self.request_url(request, proxies)
self.add_headers(
request,
stream=stream,
timeout=timeout,
verify=verify,
cert=cert,
proxies=proxies,
)

chunked = not (request.body is None or "Content-Length" in request.headers)

if isinstance(timeout, tuple):
try:
connect, read = timeout
timeout = TimeoutSauce(connect=connect, read=read)
except ValueError:
raise ValueError(
f"Invalid timeout {timeout}. Pass a (connect, read) timeout tuple, "
f"or a single float to set both timeouts to the same value."
)
elif isinstance(timeout, TimeoutSauce):
pass
else:
timeout = TimeoutSauce(connect=timeout, read=timeout)

try:
> resp = conn.urlopen(
method=request.method,
url=url,
body=request.body,
headers=request.headers,
redirect=False,
assert_same_host=False,
preload_content=False,
decode_content=False,
retries=self.max_retries,
timeout=timeout,
chunked=chunked,
)

venv/lib/python3.11/site-packages/requests/adapters.py:564:
_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _
venv/lib/python3.11/site-packages/urllib3/connectionpool.py:843: in urlopen
retries = retries.increment(
_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _

self = Retry(total=0, connect=None, read=False, redirect=None, status=None), method = 'POST', url = '/api/v5/addons/upload/', response = None
error = NameResolutionError("<urllib3.connection.HTTPSConnection object at 0x103ddc3d0>: Failed to resolve 'addons.allizom.org' ([Errno 8] nodename nor servname provided, or not known)")
_pool = <urllib3.connectionpool.HTTPSConnectionPool object at 0x103ddd790>, _stacktrace = <traceback object at 0x103ddc100>

def increment(
self,
method: str | None = None,
url: str | None = None,
response: BaseHTTPResponse | None = None,
error: Exception | None = None,
_pool: ConnectionPool | None = None,
_stacktrace: TracebackType | None = None,
) -> Self:
"""Return a new Retry object with incremented retry counters.

:param response: A response object, or None, if the server did not
return a response.
:type response: :class:`~urllib3.response.BaseHTTPResponse`
:param Exception error: An error encountered during the request, or
None if the response was received successfully.

:return: A new ``Retry`` object.
"""
if self.total is False and error:
# Disabled, indicate to re-raise the error.
raise reraise(type(error), error, _stacktrace)

total = self.total
if total is not None:
total -= 1

connect = self.connect
read = self.read
redirect = self.redirect
status_count = self.status
other = self.other
cause = "unknown"
status = None
redirect_location = None

if error and self._is_connection_error(error):
# Connect retry?
if connect is False:
raise reraise(type(error), error, _stacktrace)
elif connect is not None:
connect -= 1

elif error and self._is_read_error(error):
# Read retry?
if read is False or method is None or not self._is_method_retryable(method):
raise reraise(type(error), error, _stacktrace)
elif read is not None:
read -= 1

elif error:
# Other retry?
if other is not None:
other -= 1

elif response and response.get_redirect_location():
# Redirect retry?
if redirect is not None:
redirect -= 1
cause = "too many redirects"
response_redirect_location = response.get_redirect_location()
if response_redirect_location:
redirect_location = response_redirect_location
status = response.status

else:
# Incrementing because of a server error like a 500 in
# status_forcelist and the given method is in the allowed_methods
cause = ResponseError.GENERIC_ERROR
if response and response.status:
if status_count is not None:
status_count -= 1
cause = ResponseError.SPECIFIC_ERROR.format(status_code=response.status)
status = response.status

history = self.history + (
RequestHistory(method, url, error, status, redirect_location),
)

new_retry = self.new(
total=total,
connect=connect,
read=read,
redirect=redirect,
status=status_count,
other=other,
history=history,
)

if new_retry.is_exhausted():
reason = error or ResponseError(cause)
> raise MaxRetryError(_pool, url, reason) from reason # type: ignore[arg-type]
E urllib3.exceptions.MaxRetryError: HTTPSConnectionPool(host='addons.allizom.org', port=443): Max retries exceeded with url: /api/v5/addons/upload/ (Caused by NameResolutionError("<urllib3.connection.HTTPSConnection object at 0x103ddc3d0>: Failed to resolve 'addons.allizom.org' ([Errno 8] nodename nor servname provided, or not known)"))

venv/lib/python3.11/site-packages/urllib3/util/retry.py:519: MaxRetryError

During handling of the above exception, another exception occurred:

base_url = 'https://addons.allizom.org', session_auth = 'ldvd5ag27bkfpukx6rn2lcj0yuvakt3v'

@pytest.mark.serial
@pytest.mark.create_session("api_user")
def test_upload_extension_with_incorrect_version_number(base_url, session_auth):
"""The addon version number is defined in the manifest and needs to follow some naming rules"""
# create a minimal manifest, with an invalid 'version'
manifest = {
**payloads.minimal_manifest,
"name": "Addon with invalid version",
"version": "1abc.1.1a#c",
}
api_helpers.make_addon(manifest)
with open("sample-addons/make-addon.zip", "rb") as file:
> upload = requests.post(
url=f"{base_url}{_upload}",
headers={"Authorization": f"Session {session_auth}"},
files={"upload": file},
data={"channel": "listed"},
)

tests/api_w/test_addon_uploads.py:563:
_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _
venv/lib/python3.11/site-packages/requests/api.py:115: in post
return request("post", url, data=data, json=json, **kwargs)
venv/lib/python3.11/site-packages/requests/api.py:59: in request
return session.request(method=method, url=url, **kwargs)
venv/lib/python3.11/site-packages/requests/sessions.py:589: in request
resp = self.send(prep, **send_kwargs)
venv/lib/python3.11/site-packages/requests/sessions.py:703: in send
r = adapter.send(request, **kwargs)
_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _

self = <requests.adapters.HTTPAdapter object at 0x103ddf350>, request = <PreparedRequest [POST]>, stream = False, timeout = Timeout(connect=None, read=None, total=None), verify = True, cert = None
proxies = OrderedDict()

def send(
self, request, stream=False, timeout=None, verify=True, cert=None, proxies=None
):
"""Sends PreparedRequest object. Returns Response object.

:param request: The :class:`PreparedRequest <PreparedRequest>` being sent.
:param stream: (optional) Whether to stream the request content.
:param timeout: (optional) How long to wait for the server to send
data before giving up, as a float, or a :ref:`(connect timeout,
read timeout) <timeouts>` tuple.
:type timeout: float or tuple or urllib3 Timeout object
:param verify: (optional) Either a boolean, in which case it controls whether
we verify the server's TLS certificate, or a string, in which case it
must be a path to a CA bundle to use
:param cert: (optional) Any user-provided SSL certificate to be trusted.
:param proxies: (optional) The proxies dictionary to apply to the request.
:rtype: requests.Response
"""

try:
conn = self._get_connection(request, verify, proxies=proxies, cert=cert)
except LocationValueError as e:
raise InvalidURL(e, request=request)

self.cert_verify(conn, request.url, verify, cert)
url = self.request_url(request, proxies)
self.add_headers(
request,
stream=stream,
timeout=timeout,
verify=verify,
cert=cert,
proxies=proxies,
)

chunked = not (request.body is None or "Content-Length" in request.headers)

if isinstance(timeout, tuple):
try:
connect, read = timeout
timeout = TimeoutSauce(connect=connect, read=read)
except ValueError:
raise ValueError(
f"Invalid timeout {timeout}. Pass a (connect, read) timeout tuple, "
f"or a single float to set both timeouts to the same value."
)
elif isinstance(timeout, TimeoutSauce):
pass
else:
timeout = TimeoutSauce(connect=timeout, read=timeout)

try:
resp = conn.urlopen(
method=request.method,
url=url,
body=request.body,
headers=request.headers,
redirect=False,
assert_same_host=False,
preload_content=False,
decode_content=False,
retries=self.max_retries,
timeout=timeout,
chunked=chunked,
)

except (ProtocolError, OSError) as err:
raise ConnectionError(err, request=request)

except MaxRetryError as e:
if isinstance(e.reason, ConnectTimeoutError):
# TODO: Remove this in 3.0.0: see #2811
if not isinstance(e.reason, NewConnectionError):
raise ConnectTimeout(e, request=request)

if isinstance(e.reason, ResponseError):
raise RetryError(e, request=request)

if isinstance(e.reason, _ProxyError):
raise ProxyError(e, request=request)

if isinstance(e.reason, _SSLError):
# This branch is for urllib3 v1.22 and later.
raise SSLError(e, request=request)

> raise ConnectionError(e, request=request)
E requests.exceptions.ConnectionError: HTTPSConnectionPool(host='addons.allizom.org', port=443): Max retries exceeded with url: /api/v5/addons/upload/ (Caused by NameResolutionError("<urllib3.connection.HTTPSConnection object at 0x103ddc3d0>: Failed to resolve 'addons.allizom.org' ([Errno 8] nodename nor servname provided, or not known)"))

venv/lib/python3.11/site-packages/requests/adapters.py:597: ConnectionError
------------------------------Captured stdout call------------------------------
Manifest content: {'manifest_version': 2, 'version': '1abc.1.1a#c', 'name': 'Addon with invalid version'}
Failed tests/api_w/test_addon_uploads.py::test_upload_extension_with_put_method 0.01
self = <urllib3.connection.HTTPSConnection object at 0x103b34e50>

def _new_conn(self) -> socket.socket:
"""Establish a socket connection and set nodelay settings on it.

:return: New socket connection.
"""
try:
> sock = connection.create_connection(
(self._dns_host, self.port),
self.timeout,
source_address=self.source_address,
socket_options=self.socket_options,
)

venv/lib/python3.11/site-packages/urllib3/connection.py:196:
_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _
venv/lib/python3.11/site-packages/urllib3/util/connection.py:60: in create_connection
for res in socket.getaddrinfo(host, port, family, socket.SOCK_STREAM):
_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _

host = 'addons.allizom.org', port = 443, family = <AddressFamily.AF_UNSPEC: 0>, type = <SocketKind.SOCK_STREAM: 1>, proto = 0, flags = 0

def getaddrinfo(host, port, family=0, type=0, proto=0, flags=0):
"""Resolve host and port into list of address info entries.

Translate the host/port argument into a sequence of 5-tuples that contain
all the necessary arguments for creating a socket connected to that service.
host is a domain name, a string representation of an IPv4/v6 address or
None. port is a string service name such as 'http', a numeric port number or
None. By passing None as the value of host and port, you can pass NULL to
the underlying C API.

The family, type and proto arguments can be optionally specified in order to
narrow the list of addresses returned. Passing zero as a value for each of
these arguments selects the full range of results.
"""
# We override this function since we want to translate the numeric family
# and socket type values to enum constants.
addrlist = []
> for res in _socket.getaddrinfo(host, port, family, type, proto, flags):
E socket.gaierror: [Errno 8] nodename nor servname provided, or not known

/Library/Frameworks/Python.framework/Versions/3.11/lib/python3.11/socket.py:962: gaierror

The above exception was the direct cause of the following exception:

self = <urllib3.connectionpool.HTTPSConnectionPool object at 0x103b374d0>, method = 'POST', url = '/api/v5/addons/upload/'
body = b'--9bfe33ec25bee1e5e92041c0218fbd04\r\nContent-Disposition: form-data; name="channel"\r\n\r\nlisted\r\n--9bfe33ec25be...5\x06\x00\x00\x00\x00\x01\x00\x01\x00;\x00\x00\x00\xca\x00\x00\x00\x00\x00\r\n--9bfe33ec25bee1e5e92041c0218fbd04--\r\n'
headers = {'User-Agent': 'python-requests/2.32.0', 'Accept-Encoding': 'gzip, deflate', 'Accept': '*/*', 'Connection': 'keep-aliv...j0yuvakt3v', 'Content-Length': '529', 'Content-Type': 'multipart/form-data; boundary=9bfe33ec25bee1e5e92041c0218fbd04'}
retries = Retry(total=0, connect=None, read=False, redirect=None, status=None), redirect = False, assert_same_host = False, timeout = Timeout(connect=None, read=None, total=None), pool_timeout = None
release_conn = False, chunked = False, body_pos = None, preload_content = False, decode_content = False, response_kw = {}
parsed_url = Url(scheme=None, auth=None, host=None, port=None, path='/api/v5/addons/upload/', query=None, fragment=None), destination_scheme = None, conn = None, release_this_conn = True
http_tunnel_required = False, err = None, clean_exit = False

def urlopen( # type: ignore[override]
self,
method: str,
url: str,
body: _TYPE_BODY | None = None,
headers: typing.Mapping[str, str] | None = None,
retries: Retry | bool | int | None = None,
redirect: bool = True,
assert_same_host: bool = True,
timeout: _TYPE_TIMEOUT = _DEFAULT_TIMEOUT,
pool_timeout: int | None = None,
release_conn: bool | None = None,
chunked: bool = False,
body_pos: _TYPE_BODY_POSITION | None = None,
preload_content: bool = True,
decode_content: bool = True,
**response_kw: typing.Any,
) -> BaseHTTPResponse:
"""
Get a connection from the pool and perform an HTTP request. This is the
lowest level call for making a request, so you'll need to specify all
the raw details.

.. note::

More commonly, it's appropriate to use a convenience method
such as :meth:`request`.

.. note::

`release_conn` will only behave as expected if
`preload_content=False` because we want to make
`preload_content=False` the default behaviour someday soon without
breaking backwards compatibility.

:param method:
HTTP request method (such as GET, POST, PUT, etc.)

:param url:
The URL to perform the request on.

:param body:
Data to send in the request body, either :class:`str`, :class:`bytes`,
an iterable of :class:`str`/:class:`bytes`, or a file-like object.

:param headers:
Dictionary of custom headers to send, such as User-Agent,
If-None-Match, etc. If None, pool headers are used. If provided,
these headers completely replace any pool-specific headers.

:param retries:
Configure the number of retries to allow before raising a
:class:`~urllib3.exceptions.MaxRetryError` exception.

If ``None`` (default) will retry 3 times, see ``Retry.DEFAULT``. Pass a
:class:`~urllib3.util.retry.Retry` object for fine-grained control
over different types of retries.
Pass an integer number to retry connection errors that many times,
but no other types of errors. Pass zero to never retry.

If ``False``, then retries are disabled and any exception is raised
immediately. Also, instead of raising a MaxRetryError on redirects,
the redirect response will be returned.

:type retries: :class:`~urllib3.util.retry.Retry`, False, or an int.

:param redirect:
If True, automatically handle redirects (status codes 301, 302,
303, 307, 308). Each redirect counts as a retry. Disabling retries
will disable redirect, too.

:param assert_same_host:
If ``True``, will make sure that the host of the pool requests is
consistent else will raise HostChangedError. When ``False``, you can
use the pool on an HTTP proxy and request foreign hosts.

:param timeout:
If specified, overrides the default timeout for this one
request. It may be a float (in seconds) or an instance of
:class:`urllib3.util.Timeout`.

:param pool_timeout:
If set and the pool is set to block=True, then this method will
block for ``pool_timeout`` seconds and raise EmptyPoolError if no
connection is available within the time period.

:param bool preload_content:
If True, the response's body will be preloaded into memory.

:param bool decode_content:
If True, will attempt to decode the body based on the
'content-encoding' header.

:param release_conn:
If False, then the urlopen call will not release the connection
back into the pool once a response is received (but will release if
you read the entire contents of the response such as when
`preload_content=True`). This is useful if you're not preloading
the response's content immediately. You will need to call
``r.release_conn()`` on the response ``r`` to return the connection
back into the pool. If None, it takes the value of ``preload_content``
which defaults to ``True``.

:param bool chunked:
If True, urllib3 will send the body using chunked transfer
encoding. Otherwise, urllib3 will send the body using the standard
content-length form. Defaults to False.

:param int body_pos:
Position to seek to in file-like body in the event of a retry or
redirect. Typically this won't need to be set because urllib3 will
auto-populate the value when needed.
"""
parsed_url = parse_url(url)
destination_scheme = parsed_url.scheme

if headers is None:
headers = self.headers

if not isinstance(retries, Retry):
retries = Retry.from_int(retries, redirect=redirect, default=self.retries)

if release_conn is None:
release_conn = preload_content

# Check host
if assert_same_host and not self.is_same_host(url):
raise HostChangedError(self, url, retries)

# Ensure that the URL we're connecting to is properly encoded
if url.startswith("/"):
url = to_str(_encode_target(url))
else:
url = to_str(parsed_url.url)

conn = None

# Track whether `conn` needs to be released before
# returning/raising/recursing. Update this variable if necessary, and
# leave `release_conn` constant throughout the function. That way, if
# the function recurses, the original value of `release_conn` will be
# passed down into the recursive call, and its value will be respected.
#
# See issue #651 [1] for details.
#
# [1] <https://github.com/urllib3/urllib3/issues/651>
release_this_conn = release_conn

http_tunnel_required = connection_requires_http_tunnel(
self.proxy, self.proxy_config, destination_scheme
)

# Merge the proxy headers. Only done when not using HTTP CONNECT. We
# have to copy the headers dict so we can safely change it without those
# changes being reflected in anyone else's copy.
if not http_tunnel_required:
headers = headers.copy() # type: ignore[attr-defined]
headers.update(self.proxy_headers) # type: ignore[union-attr]

# Must keep the exception bound to a separate variable or else Python 3
# complains about UnboundLocalError.
err = None

# Keep track of whether we cleanly exited the except block. This
# ensures we do proper cleanup in finally.
clean_exit = False

# Rewind body position, if needed. Record current position
# for future rewinds in the event of a redirect/retry.
body_pos = set_file_position(body, body_pos)

try:
# Request a connection from the queue.
timeout_obj = self._get_timeout(timeout)
conn = self._get_conn(timeout=pool_timeout)

conn.timeout = timeout_obj.connect_timeout # type: ignore[assignment]

# Is this a closed/new connection that requires CONNECT tunnelling?
if self.proxy is not None and http_tunnel_required and conn.is_closed:
try:
self._prepare_proxy(conn)
except (BaseSSLError, OSError, SocketTimeout) as e:
self._raise_timeout(
err=e, url=self.proxy.url, timeout_value=conn.timeout
)
raise

# If we're going to release the connection in ``finally:``, then
# the response doesn't need to know about the connection. Otherwise
# it will also try to release it and we'll have a double-release
# mess.
response_conn = conn if not release_conn else None

# Make the request on the HTTPConnection object
> response = self._make_request(
conn,
method,
url,
timeout=timeout_obj,
body=body,
headers=headers,
chunked=chunked,
retries=retries,
response_conn=response_conn,
preload_content=preload_content,
decode_content=decode_content,
**response_kw,
)

venv/lib/python3.11/site-packages/urllib3/connectionpool.py:789:
_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _
venv/lib/python3.11/site-packages/urllib3/connectionpool.py:490: in _make_request
raise new_e
venv/lib/python3.11/site-packages/urllib3/connectionpool.py:466: in _make_request
self._validate_conn(conn)
venv/lib/python3.11/site-packages/urllib3/connectionpool.py:1095: in _validate_conn
conn.connect()
venv/lib/python3.11/site-packages/urllib3/connection.py:615: in connect
self.sock = sock = self._new_conn()
_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _

self = <urllib3.connection.HTTPSConnection object at 0x103b34e50>

def _new_conn(self) -> socket.socket:
"""Establish a socket connection and set nodelay settings on it.

:return: New socket connection.
"""
try:
sock = connection.create_connection(
(self._dns_host, self.port),
self.timeout,
source_address=self.source_address,
socket_options=self.socket_options,
)
except socket.gaierror as e:
> raise NameResolutionError(self.host, self, e) from e
E urllib3.exceptions.NameResolutionError: <urllib3.connection.HTTPSConnection object at 0x103b34e50>: Failed to resolve 'addons.allizom.org' ([Errno 8] nodename nor servname provided, or not known)

venv/lib/python3.11/site-packages/urllib3/connection.py:203: NameResolutionError

The above exception was the direct cause of the following exception:

self = <requests.adapters.HTTPAdapter object at 0x104121710>, request = <PreparedRequest [POST]>, stream = False, timeout = Timeout(connect=None, read=None, total=None), verify = True, cert = None
proxies = OrderedDict()

def send(
self, request, stream=False, timeout=None, verify=True, cert=None, proxies=None
):
"""Sends PreparedRequest object. Returns Response object.

:param request: The :class:`PreparedRequest <PreparedRequest>` being sent.
:param stream: (optional) Whether to stream the request content.
:param timeout: (optional) How long to wait for the server to send
data before giving up, as a float, or a :ref:`(connect timeout,
read timeout) <timeouts>` tuple.
:type timeout: float or tuple or urllib3 Timeout object
:param verify: (optional) Either a boolean, in which case it controls whether
we verify the server's TLS certificate, or a string, in which case it
must be a path to a CA bundle to use
:param cert: (optional) Any user-provided SSL certificate to be trusted.
:param proxies: (optional) The proxies dictionary to apply to the request.
:rtype: requests.Response
"""

try:
conn = self._get_connection(request, verify, proxies=proxies, cert=cert)
except LocationValueError as e:
raise InvalidURL(e, request=request)

self.cert_verify(conn, request.url, verify, cert)
url = self.request_url(request, proxies)
self.add_headers(
request,
stream=stream,
timeout=timeout,
verify=verify,
cert=cert,
proxies=proxies,
)

chunked = not (request.body is None or "Content-Length" in request.headers)

if isinstance(timeout, tuple):
try:
connect, read = timeout
timeout = TimeoutSauce(connect=connect, read=read)
except ValueError:
raise ValueError(
f"Invalid timeout {timeout}. Pass a (connect, read) timeout tuple, "
f"or a single float to set both timeouts to the same value."
)
elif isinstance(timeout, TimeoutSauce):
pass
else:
timeout = TimeoutSauce(connect=timeout, read=timeout)

try:
> resp = conn.urlopen(
method=request.method,
url=url,
body=request.body,
headers=request.headers,
redirect=False,
assert_same_host=False,
preload_content=False,
decode_content=False,
retries=self.max_retries,
timeout=timeout,
chunked=chunked,
)

venv/lib/python3.11/site-packages/requests/adapters.py:564:
_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _
venv/lib/python3.11/site-packages/urllib3/connectionpool.py:843: in urlopen
retries = retries.increment(
_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _

self = Retry(total=0, connect=None, read=False, redirect=None, status=None), method = 'POST', url = '/api/v5/addons/upload/', response = None
error = NameResolutionError("<urllib3.connection.HTTPSConnection object at 0x103b34e50>: Failed to resolve 'addons.allizom.org' ([Errno 8] nodename nor servname provided, or not known)")
_pool = <urllib3.connectionpool.HTTPSConnectionPool object at 0x103b374d0>, _stacktrace = <traceback object at 0x103b34840>

def increment(
self,
method: str | None = None,
url: str | None = None,
response: BaseHTTPResponse | None = None,
error: Exception | None = None,
_pool: ConnectionPool | None = None,
_stacktrace: TracebackType | None = None,
) -> Self:
"""Return a new Retry object with incremented retry counters.

:param response: A response object, or None, if the server did not
return a response.
:type response: :class:`~urllib3.response.BaseHTTPResponse`
:param Exception error: An error encountered during the request, or
None if the response was received successfully.

:return: A new ``Retry`` object.
"""
if self.total is False and error:
# Disabled, indicate to re-raise the error.
raise reraise(type(error), error, _stacktrace)

total = self.total
if total is not None:
total -= 1

connect = self.connect
read = self.read
redirect = self.redirect
status_count = self.status
other = self.other
cause = "unknown"
status = None
redirect_location = None

if error and self._is_connection_error(error):
# Connect retry?
if connect is False:
raise reraise(type(error), error, _stacktrace)
elif connect is not None:
connect -= 1

elif error and self._is_read_error(error):
# Read retry?
if read is False or method is None or not self._is_method_retryable(method):
raise reraise(type(error), error, _stacktrace)
elif read is not None:
read -= 1

elif error:
# Other retry?
if other is not None:
other -= 1

elif response and response.get_redirect_location():
# Redirect retry?
if redirect is not None:
redirect -= 1
cause = "too many redirects"
response_redirect_location = response.get_redirect_location()
if response_redirect_location:
redirect_location = response_redirect_location
status = response.status

else:
# Incrementing because of a server error like a 500 in
# status_forcelist and the given method is in the allowed_methods
cause = ResponseError.GENERIC_ERROR
if response and response.status:
if status_count is not None:
status_count -= 1
cause = ResponseError.SPECIFIC_ERROR.format(status_code=response.status)
status = response.status

history = self.history + (
RequestHistory(method, url, error, status, redirect_location),
)

new_retry = self.new(
total=total,
connect=connect,
read=read,
redirect=redirect,
status=status_count,
other=other,
history=history,
)

if new_retry.is_exhausted():
reason = error or ResponseError(cause)
> raise MaxRetryError(_pool, url, reason) from reason # type: ignore[arg-type]
E urllib3.exceptions.MaxRetryError: HTTPSConnectionPool(host='addons.allizom.org', port=443): Max retries exceeded with url: /api/v5/addons/upload/ (Caused by NameResolutionError("<urllib3.connection.HTTPSConnection object at 0x103b34e50>: Failed to resolve 'addons.allizom.org' ([Errno 8] nodename nor servname provided, or not known)"))

venv/lib/python3.11/site-packages/urllib3/util/retry.py:519: MaxRetryError

During handling of the above exception, another exception occurred:

base_url = 'https://addons.allizom.org', session_auth = 'ldvd5ag27bkfpukx6rn2lcj0yuvakt3v'

@pytest.mark.serial
@pytest.mark.create_session("api_user")
def test_upload_extension_with_put_method(base_url, session_auth):
"""Use the PUT method to create a new addon; unlike POST,
PUT requires the addon guid to be specified in the request"""
guid = f"random-guid@{reusables.get_random_string(6)}"
name = (
f"PUT-create-addon-{reusables.get_random_string(6)}-{reusables.current_date()}"
)
# create the addon manifest to be uploaded
manifest = {
**payloads.minimal_manifest,
"name": name,
"browser_specific_settings": {"gecko": {"id": guid}},
}
api_helpers.make_addon(manifest)
with open("sample-addons/make-addon.zip", "rb") as file:
> upload = requests.post(
url=f"{base_url}{_upload}",
headers={"Authorization": f"Session {session_auth}"},
files={"upload": file},
data={"channel": "listed"},
)

tests/api_w/test_addon_uploads.py:618:
_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _
venv/lib/python3.11/site-packages/requests/api.py:115: in post
return request("post", url, data=data, json=json, **kwargs)
venv/lib/python3.11/site-packages/requests/api.py:59: in request
return session.request(method=method, url=url, **kwargs)
venv/lib/python3.11/site-packages/requests/sessions.py:589: in request
resp = self.send(prep, **send_kwargs)
venv/lib/python3.11/site-packages/requests/sessions.py:703: in send
r = adapter.send(request, **kwargs)
_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _

self = <requests.adapters.HTTPAdapter object at 0x104121710>, request = <PreparedRequest [POST]>, stream = False, timeout = Timeout(connect=None, read=None, total=None), verify = True, cert = None
proxies = OrderedDict()

def send(
self, request, stream=False, timeout=None, verify=True, cert=None, proxies=None
):
"""Sends PreparedRequest object. Returns Response object.

:param request: The :class:`PreparedRequest <PreparedRequest>` being sent.
:param stream: (optional) Whether to stream the request content.
:param timeout: (optional) How long to wait for the server to send
data before giving up, as a float, or a :ref:`(connect timeout,
read timeout) <timeouts>` tuple.
:type timeout: float or tuple or urllib3 Timeout object
:param verify: (optional) Either a boolean, in which case it controls whether
we verify the server's TLS certificate, or a string, in which case it
must be a path to a CA bundle to use
:param cert: (optional) Any user-provided SSL certificate to be trusted.
:param proxies: (optional) The proxies dictionary to apply to the request.
:rtype: requests.Response
"""

try:
conn = self._get_connection(request, verify, proxies=proxies, cert=cert)
except LocationValueError as e:
raise InvalidURL(e, request=request)

self.cert_verify(conn, request.url, verify, cert)
url = self.request_url(request, proxies)
self.add_headers(
request,
stream=stream,
timeout=timeout,
verify=verify,
cert=cert,
proxies=proxies,
)

chunked = not (request.body is None or "Content-Length" in request.headers)

if isinstance(timeout, tuple):
try:
connect, read = timeout
timeout = TimeoutSauce(connect=connect, read=read)
except ValueError:
raise ValueError(
f"Invalid timeout {timeout}. Pass a (connect, read) timeout tuple, "
f"or a single float to set both timeouts to the same value."
)
elif isinstance(timeout, TimeoutSauce):
pass
else:
timeout = TimeoutSauce(connect=timeout, read=timeout)

try:
resp = conn.urlopen(
method=request.method,
url=url,
body=request.body,
headers=request.headers,
redirect=False,
assert_same_host=False,
preload_content=False,
decode_content=False,
retries=self.max_retries,
timeout=timeout,
chunked=chunked,
)

except (ProtocolError, OSError) as err:
raise ConnectionError(err, request=request)

except MaxRetryError as e:
if isinstance(e.reason, ConnectTimeoutError):
# TODO: Remove this in 3.0.0: see #2811
if not isinstance(e.reason, NewConnectionError):
raise ConnectTimeout(e, request=request)

if isinstance(e.reason, ResponseError):
raise RetryError(e, request=request)

if isinstance(e.reason, _ProxyError):
raise ProxyError(e, request=request)

if isinstance(e.reason, _SSLError):
# This branch is for urllib3 v1.22 and later.
raise SSLError(e, request=request)

> raise ConnectionError(e, request=request)
E requests.exceptions.ConnectionError: HTTPSConnectionPool(host='addons.allizom.org', port=443): Max retries exceeded with url: /api/v5/addons/upload/ (Caused by NameResolutionError("<urllib3.connection.HTTPSConnection object at 0x103b34e50>: Failed to resolve 'addons.allizom.org' ([Errno 8] nodename nor servname provided, or not known)"))

venv/lib/python3.11/site-packages/requests/adapters.py:597: ConnectionError
------------------------------Captured stdout call------------------------------
Manifest content: {'manifest_version': 2, 'version': '1.0', 'name': 'PUT-create-addon-wokcck-Sep #d, 2025', 'browser_specific_settings': {'gecko': {'id': 'random-guid@erbytw'}}}
Failed tests/api_w/test_addon_uploads.py::test_upload_extension_with_put_guid_mismatch 0.01
self = <urllib3.connection.HTTPSConnection object at 0x104bff450>

def _new_conn(self) -> socket.socket:
"""Establish a socket connection and set nodelay settings on it.

:return: New socket connection.
"""
try:
> sock = connection.create_connection(
(self._dns_host, self.port),
self.timeout,
source_address=self.source_address,
socket_options=self.socket_options,
)

venv/lib/python3.11/site-packages/urllib3/connection.py:196:
_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _
venv/lib/python3.11/site-packages/urllib3/util/connection.py:60: in create_connection
for res in socket.getaddrinfo(host, port, family, socket.SOCK_STREAM):
_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _

host = 'addons.allizom.org', port = 443, family = <AddressFamily.AF_UNSPEC: 0>, type = <SocketKind.SOCK_STREAM: 1>, proto = 0, flags = 0

def getaddrinfo(host, port, family=0, type=0, proto=0, flags=0):
"""Resolve host and port into list of address info entries.

Translate the host/port argument into a sequence of 5-tuples that contain
all the necessary arguments for creating a socket connected to that service.
host is a domain name, a string representation of an IPv4/v6 address or
None. port is a string service name such as 'http', a numeric port number or
None. By passing None as the value of host and port, you can pass NULL to
the underlying C API.

The family, type and proto arguments can be optionally specified in order to
narrow the list of addresses returned. Passing zero as a value for each of
these arguments selects the full range of results.
"""
# We override this function since we want to translate the numeric family
# and socket type values to enum constants.
addrlist = []
> for res in _socket.getaddrinfo(host, port, family, type, proto, flags):
E socket.gaierror: [Errno 8] nodename nor servname provided, or not known

/Library/Frameworks/Python.framework/Versions/3.11/lib/python3.11/socket.py:962: gaierror

The above exception was the direct cause of the following exception:

self = <urllib3.connectionpool.HTTPSConnectionPool object at 0x104bff190>, method = 'POST', url = '/api/v5/addons/upload/'
body = b'--0a39e96095cfd949c3b368cdf8bce87e\r\nContent-Disposition: form-data; name="channel"\r\n\r\nlisted\r\n--0a39e96095cf...5\x06\x00\x00\x00\x00\x01\x00\x01\x00;\x00\x00\x00\xb7\x00\x00\x00\x00\x00\r\n--0a39e96095cfd949c3b368cdf8bce87e--\r\n'
headers = {'User-Agent': 'python-requests/2.32.0', 'Accept-Encoding': 'gzip, deflate', 'Accept': '*/*', 'Connection': 'keep-aliv...j0yuvakt3v', 'Content-Length': '510', 'Content-Type': 'multipart/form-data; boundary=0a39e96095cfd949c3b368cdf8bce87e'}
retries = Retry(total=0, connect=None, read=False, redirect=None, status=None), redirect = False, assert_same_host = False, timeout = Timeout(connect=None, read=None, total=None), pool_timeout = None
release_conn = False, chunked = False, body_pos = None, preload_content = False, decode_content = False, response_kw = {}
parsed_url = Url(scheme=None, auth=None, host=None, port=None, path='/api/v5/addons/upload/', query=None, fragment=None), destination_scheme = None, conn = None, release_this_conn = True
http_tunnel_required = False, err = None, clean_exit = False

def urlopen( # type: ignore[override]
self,
method: str,
url: str,
body: _TYPE_BODY | None = None,
headers: typing.Mapping[str, str] | None = None,
retries: Retry | bool | int | None = None,
redirect: bool = True,
assert_same_host: bool = True,
timeout: _TYPE_TIMEOUT = _DEFAULT_TIMEOUT,
pool_timeout: int | None = None,
release_conn: bool | None = None,
chunked: bool = False,
body_pos: _TYPE_BODY_POSITION | None = None,
preload_content: bool = True,
decode_content: bool = True,
**response_kw: typing.Any,
) -> BaseHTTPResponse:
"""
Get a connection from the pool and perform an HTTP request. This is the
lowest level call for making a request, so you'll need to specify all
the raw details.

.. note::

More commonly, it's appropriate to use a convenience method
such as :meth:`request`.

.. note::

`release_conn` will only behave as expected if
`preload_content=False` because we want to make
`preload_content=False` the default behaviour someday soon without
breaking backwards compatibility.

:param method:
HTTP request method (such as GET, POST, PUT, etc.)

:param url:
The URL to perform the request on.

:param body:
Data to send in the request body, either :class:`str`, :class:`bytes`,
an iterable of :class:`str`/:class:`bytes`, or a file-like object.

:param headers:
Dictionary of custom headers to send, such as User-Agent,
If-None-Match, etc. If None, pool headers are used. If provided,
these headers completely replace any pool-specific headers.

:param retries:
Configure the number of retries to allow before raising a
:class:`~urllib3.exceptions.MaxRetryError` exception.

If ``None`` (default) will retry 3 times, see ``Retry.DEFAULT``. Pass a
:class:`~urllib3.util.retry.Retry` object for fine-grained control
over different types of retries.
Pass an integer number to retry connection errors that many times,
but no other types of errors. Pass zero to never retry.

If ``False``, then retries are disabled and any exception is raised
immediately. Also, instead of raising a MaxRetryError on redirects,
the redirect response will be returned.

:type retries: :class:`~urllib3.util.retry.Retry`, False, or an int.

:param redirect:
If True, automatically handle redirects (status codes 301, 302,
303, 307, 308). Each redirect counts as a retry. Disabling retries
will disable redirect, too.

:param assert_same_host:
If ``True``, will make sure that the host of the pool requests is
consistent else will raise HostChangedError. When ``False``, you can
use the pool on an HTTP proxy and request foreign hosts.

:param timeout:
If specified, overrides the default timeout for this one
request. It may be a float (in seconds) or an instance of
:class:`urllib3.util.Timeout`.

:param pool_timeout:
If set and the pool is set to block=True, then this method will
block for ``pool_timeout`` seconds and raise EmptyPoolError if no
connection is available within the time period.

:param bool preload_content:
If True, the response's body will be preloaded into memory.

:param bool decode_content:
If True, will attempt to decode the body based on the
'content-encoding' header.

:param release_conn:
If False, then the urlopen call will not release the connection
back into the pool once a response is received (but will release if
you read the entire contents of the response such as when
`preload_content=True`). This is useful if you're not preloading
the response's content immediately. You will need to call
``r.release_conn()`` on the response ``r`` to return the connection
back into the pool. If None, it takes the value of ``preload_content``
which defaults to ``True``.

:param bool chunked:
If True, urllib3 will send the body using chunked transfer
encoding. Otherwise, urllib3 will send the body using the standard
content-length form. Defaults to False.

:param int body_pos:
Position to seek to in file-like body in the event of a retry or
redirect. Typically this won't need to be set because urllib3 will
auto-populate the value when needed.
"""
parsed_url = parse_url(url)
destination_scheme = parsed_url.scheme

if headers is None:
headers = self.headers

if not isinstance(retries, Retry):
retries = Retry.from_int(retries, redirect=redirect, default=self.retries)

if release_conn is None:
release_conn = preload_content

# Check host
if assert_same_host and not self.is_same_host(url):
raise HostChangedError(self, url, retries)

# Ensure that the URL we're connecting to is properly encoded
if url.startswith("/"):
url = to_str(_encode_target(url))
else:
url = to_str(parsed_url.url)

conn = None

# Track whether `conn` needs to be released before
# returning/raising/recursing. Update this variable if necessary, and
# leave `release_conn` constant throughout the function. That way, if
# the function recurses, the original value of `release_conn` will be
# passed down into the recursive call, and its value will be respected.
#
# See issue #651 [1] for details.
#
# [1] <https://github.com/urllib3/urllib3/issues/651>
release_this_conn = release_conn

http_tunnel_required = connection_requires_http_tunnel(
self.proxy, self.proxy_config, destination_scheme
)

# Merge the proxy headers. Only done when not using HTTP CONNECT. We
# have to copy the headers dict so we can safely change it without those
# changes being reflected in anyone else's copy.
if not http_tunnel_required:
headers = headers.copy() # type: ignore[attr-defined]
headers.update(self.proxy_headers) # type: ignore[union-attr]

# Must keep the exception bound to a separate variable or else Python 3
# complains about UnboundLocalError.
err = None

# Keep track of whether we cleanly exited the except block. This
# ensures we do proper cleanup in finally.
clean_exit = False

# Rewind body position, if needed. Record current position
# for future rewinds in the event of a redirect/retry.
body_pos = set_file_position(body, body_pos)

try:
# Request a connection from the queue.
timeout_obj = self._get_timeout(timeout)
conn = self._get_conn(timeout=pool_timeout)

conn.timeout = timeout_obj.connect_timeout # type: ignore[assignment]

# Is this a closed/new connection that requires CONNECT tunnelling?
if self.proxy is not None and http_tunnel_required and conn.is_closed:
try:
self._prepare_proxy(conn)
except (BaseSSLError, OSError, SocketTimeout) as e:
self._raise_timeout(
err=e, url=self.proxy.url, timeout_value=conn.timeout
)
raise

# If we're going to release the connection in ``finally:``, then
# the response doesn't need to know about the connection. Otherwise
# it will also try to release it and we'll have a double-release
# mess.
response_conn = conn if not release_conn else None

# Make the request on the HTTPConnection object
> response = self._make_request(
conn,
method,
url,
timeout=timeout_obj,
body=body,
headers=headers,
chunked=chunked,
retries=retries,
response_conn=response_conn,
preload_content=preload_content,
decode_content=decode_content,
**response_kw,
)

venv/lib/python3.11/site-packages/urllib3/connectionpool.py:789:
_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _
venv/lib/python3.11/site-packages/urllib3/connectionpool.py:490: in _make_request
raise new_e
venv/lib/python3.11/site-packages/urllib3/connectionpool.py:466: in _make_request
self._validate_conn(conn)
venv/lib/python3.11/site-packages/urllib3/connectionpool.py:1095: in _validate_conn
conn.connect()
venv/lib/python3.11/site-packages/urllib3/connection.py:615: in connect
self.sock = sock = self._new_conn()
_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _

self = <urllib3.connection.HTTPSConnection object at 0x104bff450>

def _new_conn(self) -> socket.socket:
"""Establish a socket connection and set nodelay settings on it.

:return: New socket connection.
"""
try:
sock = connection.create_connection(
(self._dns_host, self.port),
self.timeout,
source_address=self.source_address,
socket_options=self.socket_options,
)
except socket.gaierror as e:
> raise NameResolutionError(self.host, self, e) from e
E urllib3.exceptions.NameResolutionError: <urllib3.connection.HTTPSConnection object at 0x104bff450>: Failed to resolve 'addons.allizom.org' ([Errno 8] nodename nor servname provided, or not known)

venv/lib/python3.11/site-packages/urllib3/connection.py:203: NameResolutionError

The above exception was the direct cause of the following exception:

self = <requests.adapters.HTTPAdapter object at 0x104bfe010>, request = <PreparedRequest [POST]>, stream = False, timeout = Timeout(connect=None, read=None, total=None), verify = True, cert = None
proxies = OrderedDict()

def send(
self, request, stream=False, timeout=None, verify=True, cert=None, proxies=None
):
"""Sends PreparedRequest object. Returns Response object.

:param request: The :class:`PreparedRequest <PreparedRequest>` being sent.
:param stream: (optional) Whether to stream the request content.
:param timeout: (optional) How long to wait for the server to send
data before giving up, as a float, or a :ref:`(connect timeout,
read timeout) <timeouts>` tuple.
:type timeout: float or tuple or urllib3 Timeout object
:param verify: (optional) Either a boolean, in which case it controls whether
we verify the server's TLS certificate, or a string, in which case it
must be a path to a CA bundle to use
:param cert: (optional) Any user-provided SSL certificate to be trusted.
:param proxies: (optional) The proxies dictionary to apply to the request.
:rtype: requests.Response
"""

try:
conn = self._get_connection(request, verify, proxies=proxies, cert=cert)
except LocationValueError as e:
raise InvalidURL(e, request=request)

self.cert_verify(conn, request.url, verify, cert)
url = self.request_url(request, proxies)
self.add_headers(
request,
stream=stream,
timeout=timeout,
verify=verify,
cert=cert,
proxies=proxies,
)

chunked = not (request.body is None or "Content-Length" in request.headers)

if isinstance(timeout, tuple):
try:
connect, read = timeout
timeout = TimeoutSauce(connect=connect, read=read)
except ValueError:
raise ValueError(
f"Invalid timeout {timeout}. Pass a (connect, read) timeout tuple, "
f"or a single float to set both timeouts to the same value."
)
elif isinstance(timeout, TimeoutSauce):
pass
else:
timeout = TimeoutSauce(connect=timeout, read=timeout)

try:
> resp = conn.urlopen(
method=request.method,
url=url,
body=request.body,
headers=request.headers,
redirect=False,
assert_same_host=False,
preload_content=False,
decode_content=False,
retries=self.max_retries,
timeout=timeout,
chunked=chunked,
)

venv/lib/python3.11/site-packages/requests/adapters.py:564:
_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _
venv/lib/python3.11/site-packages/urllib3/connectionpool.py:843: in urlopen
retries = retries.increment(
_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _

self = Retry(total=0, connect=None, read=False, redirect=None, status=None), method = 'POST', url = '/api/v5/addons/upload/', response = None
error = NameResolutionError("<urllib3.connection.HTTPSConnection object at 0x104bff450>: Failed to resolve 'addons.allizom.org' ([Errno 8] nodename nor servname provided, or not known)")
_pool = <urllib3.connectionpool.HTTPSConnectionPool object at 0x104bff190>, _stacktrace = <traceback object at 0x104bff500>

def increment(
self,
method: str | None = None,
url: str | None = None,
response: BaseHTTPResponse | None = None,
error: Exception | None = None,
_pool: ConnectionPool | None = None,
_stacktrace: TracebackType | None = None,
) -> Self:
"""Return a new Retry object with incremented retry counters.

:param response: A response object, or None, if the server did not
return a response.
:type response: :class:`~urllib3.response.BaseHTTPResponse`
:param Exception error: An error encountered during the request, or
None if the response was received successfully.

:return: A new ``Retry`` object.
"""
if self.total is False and error:
# Disabled, indicate to re-raise the error.
raise reraise(type(error), error, _stacktrace)

total = self.total
if total is not None:
total -= 1

connect = self.connect
read = self.read
redirect = self.redirect
status_count = self.status
other = self.other
cause = "unknown"
status = None
redirect_location = None

if error and self._is_connection_error(error):
# Connect retry?
if connect is False:
raise reraise(type(error), error, _stacktrace)
elif connect is not None:
connect -= 1

elif error and self._is_read_error(error):
# Read retry?
if read is False or method is None or not self._is_method_retryable(method):
raise reraise(type(error), error, _stacktrace)
elif read is not None:
read -= 1

elif error:
# Other retry?
if other is not None:
other -= 1

elif response and response.get_redirect_location():
# Redirect retry?
if redirect is not None:
redirect -= 1
cause = "too many redirects"
response_redirect_location = response.get_redirect_location()
if response_redirect_location:
redirect_location = response_redirect_location
status = response.status

else:
# Incrementing because of a server error like a 500 in
# status_forcelist and the given method is in the allowed_methods
cause = ResponseError.GENERIC_ERROR
if response and response.status:
if status_count is not None:
status_count -= 1
cause = ResponseError.SPECIFIC_ERROR.format(status_code=response.status)
status = response.status

history = self.history + (
RequestHistory(method, url, error, status, redirect_location),
)

new_retry = self.new(
total=total,
connect=connect,
read=read,
redirect=redirect,
status=status_count,
other=other,
history=history,
)

if new_retry.is_exhausted():
reason = error or ResponseError(cause)
> raise MaxRetryError(_pool, url, reason) from reason # type: ignore[arg-type]
E urllib3.exceptions.MaxRetryError: HTTPSConnectionPool(host='addons.allizom.org', port=443): Max retries exceeded with url: /api/v5/addons/upload/ (Caused by NameResolutionError("<urllib3.connection.HTTPSConnection object at 0x104bff450>: Failed to resolve 'addons.allizom.org' ([Errno 8] nodename nor servname provided, or not known)"))

venv/lib/python3.11/site-packages/urllib3/util/retry.py:519: MaxRetryError

During handling of the above exception, another exception occurred:

base_url = 'https://addons.allizom.org', session_auth = 'ldvd5ag27bkfpukx6rn2lcj0yuvakt3v'

@pytest.mark.serial
@pytest.mark.create_session("api_user")
def test_upload_extension_with_put_guid_mismatch(base_url, session_auth):
"""The PUT method requires the same guid to be specified in the manifest and in the request url;
this test verifies that the submission fails if there is a guid mismatch between the two
"""
guid = f"random-guid@{reusables.get_random_string(6)}"
# create the addon manifest to be uploaded
manifest = {
**payloads.minimal_manifest,
"name": "PUT-guid-mismatch",
"browser_specific_settings": {"gecko": {"id": guid}},
}
api_helpers.make_addon(manifest)
with open("sample-addons/make-addon.zip", "rb") as file:
> upload = requests.post(
url=f"{base_url}{_upload}",
headers={"Authorization": f"Session {session_auth}"},
files={"upload": file},
data={"channel": "listed"},
)

tests/api_w/test_addon_uploads.py:663:
_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _
venv/lib/python3.11/site-packages/requests/api.py:115: in post
return request("post", url, data=data, json=json, **kwargs)
venv/lib/python3.11/site-packages/requests/api.py:59: in request
return session.request(method=method, url=url, **kwargs)
venv/lib/python3.11/site-packages/requests/sessions.py:589: in request
resp = self.send(prep, **send_kwargs)
venv/lib/python3.11/site-packages/requests/sessions.py:703: in send
r = adapter.send(request, **kwargs)
_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _

self = <requests.adapters.HTTPAdapter object at 0x104bfe010>, request = <PreparedRequest [POST]>, stream = False, timeout = Timeout(connect=None, read=None, total=None), verify = True, cert = None
proxies = OrderedDict()

def send(
self, request, stream=False, timeout=None, verify=True, cert=None, proxies=None
):
"""Sends PreparedRequest object. Returns Response object.

:param request: The :class:`PreparedRequest <PreparedRequest>` being sent.
:param stream: (optional) Whether to stream the request content.
:param timeout: (optional) How long to wait for the server to send
data before giving up, as a float, or a :ref:`(connect timeout,
read timeout) <timeouts>` tuple.
:type timeout: float or tuple or urllib3 Timeout object
:param verify: (optional) Either a boolean, in which case it controls whether
we verify the server's TLS certificate, or a string, in which case it
must be a path to a CA bundle to use
:param cert: (optional) Any user-provided SSL certificate to be trusted.
:param proxies: (optional) The proxies dictionary to apply to the request.
:rtype: requests.Response
"""

try:
conn = self._get_connection(request, verify, proxies=proxies, cert=cert)
except LocationValueError as e:
raise InvalidURL(e, request=request)

self.cert_verify(conn, request.url, verify, cert)
url = self.request_url(request, proxies)
self.add_headers(
request,
stream=stream,
timeout=timeout,
verify=verify,
cert=cert,
proxies=proxies,
)

chunked = not (request.body is None or "Content-Length" in request.headers)

if isinstance(timeout, tuple):
try:
connect, read = timeout
timeout = TimeoutSauce(connect=connect, read=read)
except ValueError:
raise ValueError(
f"Invalid timeout {timeout}. Pass a (connect, read) timeout tuple, "
f"or a single float to set both timeouts to the same value."
)
elif isinstance(timeout, TimeoutSauce):
pass
else:
timeout = TimeoutSauce(connect=timeout, read=timeout)

try:
resp = conn.urlopen(
method=request.method,
url=url,
body=request.body,
headers=request.headers,
redirect=False,
assert_same_host=False,
preload_content=False,
decode_content=False,
retries=self.max_retries,
timeout=timeout,
chunked=chunked,
)

except (ProtocolError, OSError) as err:
raise ConnectionError(err, request=request)

except MaxRetryError as e:
if isinstance(e.reason, ConnectTimeoutError):
# TODO: Remove this in 3.0.0: see #2811
if not isinstance(e.reason, NewConnectionError):
raise ConnectTimeout(e, request=request)

if isinstance(e.reason, ResponseError):
raise RetryError(e, request=request)

if isinstance(e.reason, _ProxyError):
raise ProxyError(e, request=request)

if isinstance(e.reason, _SSLError):
# This branch is for urllib3 v1.22 and later.
raise SSLError(e, request=request)

> raise ConnectionError(e, request=request)
E requests.exceptions.ConnectionError: HTTPSConnectionPool(host='addons.allizom.org', port=443): Max retries exceeded with url: /api/v5/addons/upload/ (Caused by NameResolutionError("<urllib3.connection.HTTPSConnection object at 0x104bff450>: Failed to resolve 'addons.allizom.org' ([Errno 8] nodename nor servname provided, or not known)"))

venv/lib/python3.11/site-packages/requests/adapters.py:597: ConnectionError
------------------------------Captured stdout call------------------------------
Manifest content: {'manifest_version': 2, 'version': '1.0', 'name': 'PUT-guid-mismatch', 'browser_specific_settings': {'gecko': {'id': 'random-guid@svxxtv'}}}
Failed tests/api_w/test_addon_uploads.py::test_upload_extension_with_put_no_guid_in_manifest 0.00
self = <urllib3.connection.HTTPSConnection object at 0x103b699d0>

def _new_conn(self) -> socket.socket:
"""Establish a socket connection and set nodelay settings on it.

:return: New socket connection.
"""
try:
> sock = connection.create_connection(
(self._dns_host, self.port),
self.timeout,
source_address=self.source_address,
socket_options=self.socket_options,
)

venv/lib/python3.11/site-packages/urllib3/connection.py:196:
_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _
venv/lib/python3.11/site-packages/urllib3/util/connection.py:60: in create_connection
for res in socket.getaddrinfo(host, port, family, socket.SOCK_STREAM):
_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _

host = 'addons.allizom.org', port = 443, family = <AddressFamily.AF_UNSPEC: 0>, type = <SocketKind.SOCK_STREAM: 1>, proto = 0, flags = 0

def getaddrinfo(host, port, family=0, type=0, proto=0, flags=0):
"""Resolve host and port into list of address info entries.

Translate the host/port argument into a sequence of 5-tuples that contain
all the necessary arguments for creating a socket connected to that service.
host is a domain name, a string representation of an IPv4/v6 address or
None. port is a string service name such as 'http', a numeric port number or
None. By passing None as the value of host and port, you can pass NULL to
the underlying C API.

The family, type and proto arguments can be optionally specified in order to
narrow the list of addresses returned. Passing zero as a value for each of
these arguments selects the full range of results.
"""
# We override this function since we want to translate the numeric family
# and socket type values to enum constants.
addrlist = []
> for res in _socket.getaddrinfo(host, port, family, type, proto, flags):
E socket.gaierror: [Errno 8] nodename nor servname provided, or not known

/Library/Frameworks/Python.framework/Versions/3.11/lib/python3.11/socket.py:962: gaierror

The above exception was the direct cause of the following exception:

self = <urllib3.connectionpool.HTTPSConnectionPool object at 0x103b6a050>, method = 'POST', url = '/api/v5/addons/upload/'
body = b'--cce83132d07a70bdfdadd0fc98a901f9\r\nContent-Disposition: form-data; name="channel"\r\n\r\nlisted\r\n--cce83132d07a...\x05\x06\x00\x00\x00\x00\x01\x00\x01\x00_\x00\x00\x00f\x00\x00\x00\x00\x00\r\n--cce83132d07a70bdfdadd0fc98a901f9--\r\n'
headers = {'User-Agent': 'python-requests/2.32.0', 'Accept-Encoding': 'gzip, deflate', 'Accept': '*/*', 'Connection': 'keep-aliv...j0yuvakt3v', 'Content-Length': '467', 'Content-Type': 'multipart/form-data; boundary=cce83132d07a70bdfdadd0fc98a901f9'}
retries = Retry(total=0, connect=None, read=False, redirect=None, status=None), redirect = False, assert_same_host = False, timeout = Timeout(connect=None, read=None, total=None), pool_timeout = None
release_conn = False, chunked = False, body_pos = None, preload_content = False, decode_content = False, response_kw = {}
parsed_url = Url(scheme=None, auth=None, host=None, port=None, path='/api/v5/addons/upload/', query=None, fragment=None), destination_scheme = None, conn = None, release_this_conn = True
http_tunnel_required = False, err = None, clean_exit = False

def urlopen( # type: ignore[override]
self,
method: str,
url: str,
body: _TYPE_BODY | None = None,
headers: typing.Mapping[str, str] | None = None,
retries: Retry | bool | int | None = None,
redirect: bool = True,
assert_same_host: bool = True,
timeout: _TYPE_TIMEOUT = _DEFAULT_TIMEOUT,
pool_timeout: int | None = None,
release_conn: bool | None = None,
chunked: bool = False,
body_pos: _TYPE_BODY_POSITION | None = None,
preload_content: bool = True,
decode_content: bool = True,
**response_kw: typing.Any,
) -> BaseHTTPResponse:
"""
Get a connection from the pool and perform an HTTP request. This is the
lowest level call for making a request, so you'll need to specify all
the raw details.

.. note::

More commonly, it's appropriate to use a convenience method
such as :meth:`request`.

.. note::

`release_conn` will only behave as expected if
`preload_content=False` because we want to make
`preload_content=False` the default behaviour someday soon without
breaking backwards compatibility.

:param method:
HTTP request method (such as GET, POST, PUT, etc.)

:param url:
The URL to perform the request on.

:param body:
Data to send in the request body, either :class:`str`, :class:`bytes`,
an iterable of :class:`str`/:class:`bytes`, or a file-like object.

:param headers:
Dictionary of custom headers to send, such as User-Agent,
If-None-Match, etc. If None, pool headers are used. If provided,
these headers completely replace any pool-specific headers.

:param retries:
Configure the number of retries to allow before raising a
:class:`~urllib3.exceptions.MaxRetryError` exception.

If ``None`` (default) will retry 3 times, see ``Retry.DEFAULT``. Pass a
:class:`~urllib3.util.retry.Retry` object for fine-grained control
over different types of retries.
Pass an integer number to retry connection errors that many times,
but no other types of errors. Pass zero to never retry.

If ``False``, then retries are disabled and any exception is raised
immediately. Also, instead of raising a MaxRetryError on redirects,
the redirect response will be returned.

:type retries: :class:`~urllib3.util.retry.Retry`, False, or an int.

:param redirect:
If True, automatically handle redirects (status codes 301, 302,
303, 307, 308). Each redirect counts as a retry. Disabling retries
will disable redirect, too.

:param assert_same_host:
If ``True``, will make sure that the host of the pool requests is
consistent else will raise HostChangedError. When ``False``, you can
use the pool on an HTTP proxy and request foreign hosts.

:param timeout:
If specified, overrides the default timeout for this one
request. It may be a float (in seconds) or an instance of
:class:`urllib3.util.Timeout`.

:param pool_timeout:
If set and the pool is set to block=True, then this method will
block for ``pool_timeout`` seconds and raise EmptyPoolError if no
connection is available within the time period.

:param bool preload_content:
If True, the response's body will be preloaded into memory.

:param bool decode_content:
If True, will attempt to decode the body based on the
'content-encoding' header.

:param release_conn:
If False, then the urlopen call will not release the connection
back into the pool once a response is received (but will release if
you read the entire contents of the response such as when
`preload_content=True`). This is useful if you're not preloading
the response's content immediately. You will need to call
``r.release_conn()`` on the response ``r`` to return the connection
back into the pool. If None, it takes the value of ``preload_content``
which defaults to ``True``.

:param bool chunked:
If True, urllib3 will send the body using chunked transfer
encoding. Otherwise, urllib3 will send the body using the standard
content-length form. Defaults to False.

:param int body_pos:
Position to seek to in file-like body in the event of a retry or
redirect. Typically this won't need to be set because urllib3 will
auto-populate the value when needed.
"""
parsed_url = parse_url(url)
destination_scheme = parsed_url.scheme

if headers is None:
headers = self.headers

if not isinstance(retries, Retry):
retries = Retry.from_int(retries, redirect=redirect, default=self.retries)

if release_conn is None:
release_conn = preload_content

# Check host
if assert_same_host and not self.is_same_host(url):
raise HostChangedError(self, url, retries)

# Ensure that the URL we're connecting to is properly encoded
if url.startswith("/"):
url = to_str(_encode_target(url))
else:
url = to_str(parsed_url.url)

conn = None

# Track whether `conn` needs to be released before
# returning/raising/recursing. Update this variable if necessary, and
# leave `release_conn` constant throughout the function. That way, if
# the function recurses, the original value of `release_conn` will be
# passed down into the recursive call, and its value will be respected.
#
# See issue #651 [1] for details.
#
# [1] <https://github.com/urllib3/urllib3/issues/651>
release_this_conn = release_conn

http_tunnel_required = connection_requires_http_tunnel(
self.proxy, self.proxy_config, destination_scheme
)

# Merge the proxy headers. Only done when not using HTTP CONNECT. We
# have to copy the headers dict so we can safely change it without those
# changes being reflected in anyone else's copy.
if not http_tunnel_required:
headers = headers.copy() # type: ignore[attr-defined]
headers.update(self.proxy_headers) # type: ignore[union-attr]

# Must keep the exception bound to a separate variable or else Python 3
# complains about UnboundLocalError.
err = None

# Keep track of whether we cleanly exited the except block. This
# ensures we do proper cleanup in finally.
clean_exit = False

# Rewind body position, if needed. Record current position
# for future rewinds in the event of a redirect/retry.
body_pos = set_file_position(body, body_pos)

try:
# Request a connection from the queue.
timeout_obj = self._get_timeout(timeout)
conn = self._get_conn(timeout=pool_timeout)

conn.timeout = timeout_obj.connect_timeout # type: ignore[assignment]

# Is this a closed/new connection that requires CONNECT tunnelling?
if self.proxy is not None and http_tunnel_required and conn.is_closed:
try:
self._prepare_proxy(conn)
except (BaseSSLError, OSError, SocketTimeout) as e:
self._raise_timeout(
err=e, url=self.proxy.url, timeout_value=conn.timeout
)
raise

# If we're going to release the connection in ``finally:``, then
# the response doesn't need to know about the connection. Otherwise
# it will also try to release it and we'll have a double-release
# mess.
response_conn = conn if not release_conn else None

# Make the request on the HTTPConnection object
> response = self._make_request(
conn,
method,
url,
timeout=timeout_obj,
body=body,
headers=headers,
chunked=chunked,
retries=retries,
response_conn=response_conn,
preload_content=preload_content,
decode_content=decode_content,
**response_kw,
)

venv/lib/python3.11/site-packages/urllib3/connectionpool.py:789:
_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _
venv/lib/python3.11/site-packages/urllib3/connectionpool.py:490: in _make_request
raise new_e
venv/lib/python3.11/site-packages/urllib3/connectionpool.py:466: in _make_request
self._validate_conn(conn)
venv/lib/python3.11/site-packages/urllib3/connectionpool.py:1095: in _validate_conn
conn.connect()
venv/lib/python3.11/site-packages/urllib3/connection.py:615: in connect
self.sock = sock = self._new_conn()
_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _

self = <urllib3.connection.HTTPSConnection object at 0x103b699d0>

def _new_conn(self) -> socket.socket:
"""Establish a socket connection and set nodelay settings on it.

:return: New socket connection.
"""
try:
sock = connection.create_connection(
(self._dns_host, self.port),
self.timeout,
source_address=self.source_address,
socket_options=self.socket_options,
)
except socket.gaierror as e:
> raise NameResolutionError(self.host, self, e) from e
E urllib3.exceptions.NameResolutionError: <urllib3.connection.HTTPSConnection object at 0x103b699d0>: Failed to resolve 'addons.allizom.org' ([Errno 8] nodename nor servname provided, or not known)

venv/lib/python3.11/site-packages/urllib3/connection.py:203: NameResolutionError

The above exception was the direct cause of the following exception:

self = <requests.adapters.HTTPAdapter object at 0x103b6b7d0>, request = <PreparedRequest [POST]>, stream = False, timeout = Timeout(connect=None, read=None, total=None), verify = True, cert = None
proxies = OrderedDict()

def send(
self, request, stream=False, timeout=None, verify=True, cert=None, proxies=None
):
"""Sends PreparedRequest object. Returns Response object.

:param request: The :class:`PreparedRequest <PreparedRequest>` being sent.
:param stream: (optional) Whether to stream the request content.
:param timeout: (optional) How long to wait for the server to send
data before giving up, as a float, or a :ref:`(connect timeout,
read timeout) <timeouts>` tuple.
:type timeout: float or tuple or urllib3 Timeout object
:param verify: (optional) Either a boolean, in which case it controls whether
we verify the server's TLS certificate, or a string, in which case it
must be a path to a CA bundle to use
:param cert: (optional) Any user-provided SSL certificate to be trusted.
:param proxies: (optional) The proxies dictionary to apply to the request.
:rtype: requests.Response
"""

try:
conn = self._get_connection(request, verify, proxies=proxies, cert=cert)
except LocationValueError as e:
raise InvalidURL(e, request=request)

self.cert_verify(conn, request.url, verify, cert)
url = self.request_url(request, proxies)
self.add_headers(
request,
stream=stream,
timeout=timeout,
verify=verify,
cert=cert,
proxies=proxies,
)

chunked = not (request.body is None or "Content-Length" in request.headers)

if isinstance(timeout, tuple):
try:
connect, read = timeout
timeout = TimeoutSauce(connect=connect, read=read)
except ValueError:
raise ValueError(
f"Invalid timeout {timeout}. Pass a (connect, read) timeout tuple, "
f"or a single float to set both timeouts to the same value."
)
elif isinstance(timeout, TimeoutSauce):
pass
else:
timeout = TimeoutSauce(connect=timeout, read=timeout)

try:
> resp = conn.urlopen(
method=request.method,
url=url,
body=request.body,
headers=request.headers,
redirect=False,
assert_same_host=False,
preload_content=False,
decode_content=False,
retries=self.max_retries,
timeout=timeout,
chunked=chunked,
)

venv/lib/python3.11/site-packages/requests/adapters.py:564:
_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _
venv/lib/python3.11/site-packages/urllib3/connectionpool.py:843: in urlopen
retries = retries.increment(
_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _

self = Retry(total=0, connect=None, read=False, redirect=None, status=None), method = 'POST', url = '/api/v5/addons/upload/', response = None
error = NameResolutionError("<urllib3.connection.HTTPSConnection object at 0x103b699d0>: Failed to resolve 'addons.allizom.org' ([Errno 8] nodename nor servname provided, or not known)")
_pool = <urllib3.connectionpool.HTTPSConnectionPool object at 0x103b6a050>, _stacktrace = <traceback object at 0x103b6bf40>

def increment(
self,
method: str | None = None,
url: str | None = None,
response: BaseHTTPResponse | None = None,
error: Exception | None = None,
_pool: ConnectionPool | None = None,
_stacktrace: TracebackType | None = None,
) -> Self:
"""Return a new Retry object with incremented retry counters.

:param response: A response object, or None, if the server did not
return a response.
:type response: :class:`~urllib3.response.BaseHTTPResponse`
:param Exception error: An error encountered during the request, or
None if the response was received successfully.

:return: A new ``Retry`` object.
"""
if self.total is False and error:
# Disabled, indicate to re-raise the error.
raise reraise(type(error), error, _stacktrace)

total = self.total
if total is not None:
total -= 1

connect = self.connect
read = self.read
redirect = self.redirect
status_count = self.status
other = self.other
cause = "unknown"
status = None
redirect_location = None

if error and self._is_connection_error(error):
# Connect retry?
if connect is False:
raise reraise(type(error), error, _stacktrace)
elif connect is not None:
connect -= 1

elif error and self._is_read_error(error):
# Read retry?
if read is False or method is None or not self._is_method_retryable(method):
raise reraise(type(error), error, _stacktrace)
elif read is not None:
read -= 1

elif error:
# Other retry?
if other is not None:
other -= 1

elif response and response.get_redirect_location():
# Redirect retry?
if redirect is not None:
redirect -= 1
cause = "too many redirects"
response_redirect_location = response.get_redirect_location()
if response_redirect_location:
redirect_location = response_redirect_location
status = response.status

else:
# Incrementing because of a server error like a 500 in
# status_forcelist and the given method is in the allowed_methods
cause = ResponseError.GENERIC_ERROR
if response and response.status:
if status_count is not None:
status_count -= 1
cause = ResponseError.SPECIFIC_ERROR.format(status_code=response.status)
status = response.status

history = self.history + (
RequestHistory(method, url, error, status, redirect_location),
)

new_retry = self.new(
total=total,
connect=connect,
read=read,
redirect=redirect,
status=status_count,
other=other,
history=history,
)

if new_retry.is_exhausted():
reason = error or ResponseError(cause)
> raise MaxRetryError(_pool, url, reason) from reason # type: ignore[arg-type]
E urllib3.exceptions.MaxRetryError: HTTPSConnectionPool(host='addons.allizom.org', port=443): Max retries exceeded with url: /api/v5/addons/upload/ (Caused by NameResolutionError("<urllib3.connection.HTTPSConnection object at 0x103b699d0>: Failed to resolve 'addons.allizom.org' ([Errno 8] nodename nor servname provided, or not known)"))

venv/lib/python3.11/site-packages/urllib3/util/retry.py:519: MaxRetryError

During handling of the above exception, another exception occurred:

base_url = 'https://addons.allizom.org', session_auth = 'ldvd5ag27bkfpukx6rn2lcj0yuvakt3v'

@pytest.mark.serial
@pytest.mark.create_session("api_user")
def test_upload_extension_with_put_no_guid_in_manifest(base_url, session_auth):
"""The PUT method requires a guid to be specified in the manifest;
if no guid is specified, the request should fail"""
with open("sample-addons/listed-addon.zip", "rb") as file:
> upload = requests.post(
url=f"{base_url}{_upload}",
headers={"Authorization": f"Session {session_auth}"},
files={"upload": file},
data={"channel": "listed"},
)

tests/api_w/test_addon_uploads.py:698:
_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _
venv/lib/python3.11/site-packages/requests/api.py:115: in post
return request("post", url, data=data, json=json, **kwargs)
venv/lib/python3.11/site-packages/requests/api.py:59: in request
return session.request(method=method, url=url, **kwargs)
venv/lib/python3.11/site-packages/requests/sessions.py:589: in request
resp = self.send(prep, **send_kwargs)
venv/lib/python3.11/site-packages/requests/sessions.py:703: in send
r = adapter.send(request, **kwargs)
_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _

self = <requests.adapters.HTTPAdapter object at 0x103b6b7d0>, request = <PreparedRequest [POST]>, stream = False, timeout = Timeout(connect=None, read=None, total=None), verify = True, cert = None
proxies = OrderedDict()

def send(
self, request, stream=False, timeout=None, verify=True, cert=None, proxies=None
):
"""Sends PreparedRequest object. Returns Response object.

:param request: The :class:`PreparedRequest <PreparedRequest>` being sent.
:param stream: (optional) Whether to stream the request content.
:param timeout: (optional) How long to wait for the server to send
data before giving up, as a float, or a :ref:`(connect timeout,
read timeout) <timeouts>` tuple.
:type timeout: float or tuple or urllib3 Timeout object
:param verify: (optional) Either a boolean, in which case it controls whether
we verify the server's TLS certificate, or a string, in which case it
must be a path to a CA bundle to use
:param cert: (optional) Any user-provided SSL certificate to be trusted.
:param proxies: (optional) The proxies dictionary to apply to the request.
:rtype: requests.Response
"""

try:
conn = self._get_connection(request, verify, proxies=proxies, cert=cert)
except LocationValueError as e:
raise InvalidURL(e, request=request)

self.cert_verify(conn, request.url, verify, cert)
url = self.request_url(request, proxies)
self.add_headers(
request,
stream=stream,
timeout=timeout,
verify=verify,
cert=cert,
proxies=proxies,
)

chunked = not (request.body is None or "Content-Length" in request.headers)

if isinstance(timeout, tuple):
try:
connect, read = timeout
timeout = TimeoutSauce(connect=connect, read=read)
except ValueError:
raise ValueError(
f"Invalid timeout {timeout}. Pass a (connect, read) timeout tuple, "
f"or a single float to set both timeouts to the same value."
)
elif isinstance(timeout, TimeoutSauce):
pass
else:
timeout = TimeoutSauce(connect=timeout, read=timeout)

try:
resp = conn.urlopen(
method=request.method,
url=url,
body=request.body,
headers=request.headers,
redirect=False,
assert_same_host=False,
preload_content=False,
decode_content=False,
retries=self.max_retries,
timeout=timeout,
chunked=chunked,
)

except (ProtocolError, OSError) as err:
raise ConnectionError(err, request=request)

except MaxRetryError as e:
if isinstance(e.reason, ConnectTimeoutError):
# TODO: Remove this in 3.0.0: see #2811
if not isinstance(e.reason, NewConnectionError):
raise ConnectTimeout(e, request=request)

if isinstance(e.reason, ResponseError):
raise RetryError(e, request=request)

if isinstance(e.reason, _ProxyError):
raise ProxyError(e, request=request)

if isinstance(e.reason, _SSLError):
# This branch is for urllib3 v1.22 and later.
raise SSLError(e, request=request)

> raise ConnectionError(e, request=request)
E requests.exceptions.ConnectionError: HTTPSConnectionPool(host='addons.allizom.org', port=443): Max retries exceeded with url: /api/v5/addons/upload/ (Caused by NameResolutionError("<urllib3.connection.HTTPSConnection object at 0x103b699d0>: Failed to resolve 'addons.allizom.org' ([Errno 8] nodename nor servname provided, or not known)"))

venv/lib/python3.11/site-packages/requests/adapters.py:597: ConnectionError
Failed tests/api_w/test_addon_uploads.py::test_upload_extension_with_put_no_guid_in_request 0.02
self = <urllib3.connection.HTTPSConnection object at 0x104bc3ad0>

def _new_conn(self) -> socket.socket:
"""Establish a socket connection and set nodelay settings on it.

:return: New socket connection.
"""
try:
> sock = connection.create_connection(
(self._dns_host, self.port),
self.timeout,
source_address=self.source_address,
socket_options=self.socket_options,
)

venv/lib/python3.11/site-packages/urllib3/connection.py:196:
_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _
venv/lib/python3.11/site-packages/urllib3/util/connection.py:60: in create_connection
for res in socket.getaddrinfo(host, port, family, socket.SOCK_STREAM):
_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _

host = 'addons.allizom.org', port = 443, family = <AddressFamily.AF_UNSPEC: 0>, type = <SocketKind.SOCK_STREAM: 1>, proto = 0, flags = 0

def getaddrinfo(host, port, family=0, type=0, proto=0, flags=0):
"""Resolve host and port into list of address info entries.

Translate the host/port argument into a sequence of 5-tuples that contain
all the necessary arguments for creating a socket connected to that service.
host is a domain name, a string representation of an IPv4/v6 address or
None. port is a string service name such as 'http', a numeric port number or
None. By passing None as the value of host and port, you can pass NULL to
the underlying C API.

The family, type and proto arguments can be optionally specified in order to
narrow the list of addresses returned. Passing zero as a value for each of
these arguments selects the full range of results.
"""
# We override this function since we want to translate the numeric family
# and socket type values to enum constants.
addrlist = []
> for res in _socket.getaddrinfo(host, port, family, type, proto, flags):
E socket.gaierror: [Errno 8] nodename nor servname provided, or not known

/Library/Frameworks/Python.framework/Versions/3.11/lib/python3.11/socket.py:962: gaierror

The above exception was the direct cause of the following exception:

self = <urllib3.connectionpool.HTTPSConnectionPool object at 0x104bc2d50>, method = 'POST', url = '/api/v5/addons/upload/'
body = b'--f62a7dd2b717f51d2c336b43f4156188\r\nContent-Disposition: form-data; name="channel"\r\n\r\nlisted\r\n--f62a7dd2b717...5\x06\x00\x00\x00\x00\x01\x00\x01\x00;\x00\x00\x00\xc0\x00\x00\x00\x00\x00\r\n--f62a7dd2b717f51d2c336b43f4156188--\r\n'
headers = {'User-Agent': 'python-requests/2.32.0', 'Accept-Encoding': 'gzip, deflate', 'Accept': '*/*', 'Connection': 'keep-aliv...j0yuvakt3v', 'Content-Length': '519', 'Content-Type': 'multipart/form-data; boundary=f62a7dd2b717f51d2c336b43f4156188'}
retries = Retry(total=0, connect=None, read=False, redirect=None, status=None), redirect = False, assert_same_host = False, timeout = Timeout(connect=None, read=None, total=None), pool_timeout = None
release_conn = False, chunked = False, body_pos = None, preload_content = False, decode_content = False, response_kw = {}
parsed_url = Url(scheme=None, auth=None, host=None, port=None, path='/api/v5/addons/upload/', query=None, fragment=None), destination_scheme = None, conn = None, release_this_conn = True
http_tunnel_required = False, err = None, clean_exit = False

def urlopen( # type: ignore[override]
self,
method: str,
url: str,
body: _TYPE_BODY | None = None,
headers: typing.Mapping[str, str] | None = None,
retries: Retry | bool | int | None = None,
redirect: bool = True,
assert_same_host: bool = True,
timeout: _TYPE_TIMEOUT = _DEFAULT_TIMEOUT,
pool_timeout: int | None = None,
release_conn: bool | None = None,
chunked: bool = False,
body_pos: _TYPE_BODY_POSITION | None = None,
preload_content: bool = True,
decode_content: bool = True,
**response_kw: typing.Any,
) -> BaseHTTPResponse:
"""
Get a connection from the pool and perform an HTTP request. This is the
lowest level call for making a request, so you'll need to specify all
the raw details.

.. note::

More commonly, it's appropriate to use a convenience method
such as :meth:`request`.

.. note::

`release_conn` will only behave as expected if
`preload_content=False` because we want to make
`preload_content=False` the default behaviour someday soon without
breaking backwards compatibility.

:param method:
HTTP request method (such as GET, POST, PUT, etc.)

:param url:
The URL to perform the request on.

:param body:
Data to send in the request body, either :class:`str`, :class:`bytes`,
an iterable of :class:`str`/:class:`bytes`, or a file-like object.

:param headers:
Dictionary of custom headers to send, such as User-Agent,
If-None-Match, etc. If None, pool headers are used. If provided,
these headers completely replace any pool-specific headers.

:param retries:
Configure the number of retries to allow before raising a
:class:`~urllib3.exceptions.MaxRetryError` exception.

If ``None`` (default) will retry 3 times, see ``Retry.DEFAULT``. Pass a
:class:`~urllib3.util.retry.Retry` object for fine-grained control
over different types of retries.
Pass an integer number to retry connection errors that many times,
but no other types of errors. Pass zero to never retry.

If ``False``, then retries are disabled and any exception is raised
immediately. Also, instead of raising a MaxRetryError on redirects,
the redirect response will be returned.

:type retries: :class:`~urllib3.util.retry.Retry`, False, or an int.

:param redirect:
If True, automatically handle redirects (status codes 301, 302,
303, 307, 308). Each redirect counts as a retry. Disabling retries
will disable redirect, too.

:param assert_same_host:
If ``True``, will make sure that the host of the pool requests is
consistent else will raise HostChangedError. When ``False``, you can
use the pool on an HTTP proxy and request foreign hosts.

:param timeout:
If specified, overrides the default timeout for this one
request. It may be a float (in seconds) or an instance of
:class:`urllib3.util.Timeout`.

:param pool_timeout:
If set and the pool is set to block=True, then this method will
block for ``pool_timeout`` seconds and raise EmptyPoolError if no
connection is available within the time period.

:param bool preload_content:
If True, the response's body will be preloaded into memory.

:param bool decode_content:
If True, will attempt to decode the body based on the
'content-encoding' header.

:param release_conn:
If False, then the urlopen call will not release the connection
back into the pool once a response is received (but will release if
you read the entire contents of the response such as when
`preload_content=True`). This is useful if you're not preloading
the response's content immediately. You will need to call
``r.release_conn()`` on the response ``r`` to return the connection
back into the pool. If None, it takes the value of ``preload_content``
which defaults to ``True``.

:param bool chunked:
If True, urllib3 will send the body using chunked transfer
encoding. Otherwise, urllib3 will send the body using the standard
content-length form. Defaults to False.

:param int body_pos:
Position to seek to in file-like body in the event of a retry or
redirect. Typically this won't need to be set because urllib3 will
auto-populate the value when needed.
"""
parsed_url = parse_url(url)
destination_scheme = parsed_url.scheme

if headers is None:
headers = self.headers

if not isinstance(retries, Retry):
retries = Retry.from_int(retries, redirect=redirect, default=self.retries)

if release_conn is None:
release_conn = preload_content

# Check host
if assert_same_host and not self.is_same_host(url):
raise HostChangedError(self, url, retries)

# Ensure that the URL we're connecting to is properly encoded
if url.startswith("/"):
url = to_str(_encode_target(url))
else:
url = to_str(parsed_url.url)

conn = None

# Track whether `conn` needs to be released before
# returning/raising/recursing. Update this variable if necessary, and
# leave `release_conn` constant throughout the function. That way, if
# the function recurses, the original value of `release_conn` will be
# passed down into the recursive call, and its value will be respected.
#
# See issue #651 [1] for details.
#
# [1] <https://github.com/urllib3/urllib3/issues/651>
release_this_conn = release_conn

http_tunnel_required = connection_requires_http_tunnel(
self.proxy, self.proxy_config, destination_scheme
)

# Merge the proxy headers. Only done when not using HTTP CONNECT. We
# have to copy the headers dict so we can safely change it without those
# changes being reflected in anyone else's copy.
if not http_tunnel_required:
headers = headers.copy() # type: ignore[attr-defined]
headers.update(self.proxy_headers) # type: ignore[union-attr]

# Must keep the exception bound to a separate variable or else Python 3
# complains about UnboundLocalError.
err = None

# Keep track of whether we cleanly exited the except block. This
# ensures we do proper cleanup in finally.
clean_exit = False

# Rewind body position, if needed. Record current position
# for future rewinds in the event of a redirect/retry.
body_pos = set_file_position(body, body_pos)

try:
# Request a connection from the queue.
timeout_obj = self._get_timeout(timeout)
conn = self._get_conn(timeout=pool_timeout)

conn.timeout = timeout_obj.connect_timeout # type: ignore[assignment]

# Is this a closed/new connection that requires CONNECT tunnelling?
if self.proxy is not None and http_tunnel_required and conn.is_closed:
try:
self._prepare_proxy(conn)
except (BaseSSLError, OSError, SocketTimeout) as e:
self._raise_timeout(
err=e, url=self.proxy.url, timeout_value=conn.timeout
)
raise

# If we're going to release the connection in ``finally:``, then
# the response doesn't need to know about the connection. Otherwise
# it will also try to release it and we'll have a double-release
# mess.
response_conn = conn if not release_conn else None

# Make the request on the HTTPConnection object
> response = self._make_request(
conn,
method,
url,
timeout=timeout_obj,
body=body,
headers=headers,
chunked=chunked,
retries=retries,
response_conn=response_conn,
preload_content=preload_content,
decode_content=decode_content,
**response_kw,
)

venv/lib/python3.11/site-packages/urllib3/connectionpool.py:789:
_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _
venv/lib/python3.11/site-packages/urllib3/connectionpool.py:490: in _make_request
raise new_e
venv/lib/python3.11/site-packages/urllib3/connectionpool.py:466: in _make_request
self._validate_conn(conn)
venv/lib/python3.11/site-packages/urllib3/connectionpool.py:1095: in _validate_conn
conn.connect()
venv/lib/python3.11/site-packages/urllib3/connection.py:615: in connect
self.sock = sock = self._new_conn()
_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _

self = <urllib3.connection.HTTPSConnection object at 0x104bc3ad0>

def _new_conn(self) -> socket.socket:
"""Establish a socket connection and set nodelay settings on it.

:return: New socket connection.
"""
try:
sock = connection.create_connection(
(self._dns_host, self.port),
self.timeout,
source_address=self.source_address,
socket_options=self.socket_options,
)
except socket.gaierror as e:
> raise NameResolutionError(self.host, self, e) from e
E urllib3.exceptions.NameResolutionError: <urllib3.connection.HTTPSConnection object at 0x104bc3ad0>: Failed to resolve 'addons.allizom.org' ([Errno 8] nodename nor servname provided, or not known)

venv/lib/python3.11/site-packages/urllib3/connection.py:203: NameResolutionError

The above exception was the direct cause of the following exception:

self = <requests.adapters.HTTPAdapter object at 0x1040d0390>, request = <PreparedRequest [POST]>, stream = False, timeout = Timeout(connect=None, read=None, total=None), verify = True, cert = None
proxies = OrderedDict()

def send(
self, request, stream=False, timeout=None, verify=True, cert=None, proxies=None
):
"""Sends PreparedRequest object. Returns Response object.

:param request: The :class:`PreparedRequest <PreparedRequest>` being sent.
:param stream: (optional) Whether to stream the request content.
:param timeout: (optional) How long to wait for the server to send
data before giving up, as a float, or a :ref:`(connect timeout,
read timeout) <timeouts>` tuple.
:type timeout: float or tuple or urllib3 Timeout object
:param verify: (optional) Either a boolean, in which case it controls whether
we verify the server's TLS certificate, or a string, in which case it
must be a path to a CA bundle to use
:param cert: (optional) Any user-provided SSL certificate to be trusted.
:param proxies: (optional) The proxies dictionary to apply to the request.
:rtype: requests.Response
"""

try:
conn = self._get_connection(request, verify, proxies=proxies, cert=cert)
except LocationValueError as e:
raise InvalidURL(e, request=request)

self.cert_verify(conn, request.url, verify, cert)
url = self.request_url(request, proxies)
self.add_headers(
request,
stream=stream,
timeout=timeout,
verify=verify,
cert=cert,
proxies=proxies,
)

chunked = not (request.body is None or "Content-Length" in request.headers)

if isinstance(timeout, tuple):
try:
connect, read = timeout
timeout = TimeoutSauce(connect=connect, read=read)
except ValueError:
raise ValueError(
f"Invalid timeout {timeout}. Pass a (connect, read) timeout tuple, "
f"or a single float to set both timeouts to the same value."
)
elif isinstance(timeout, TimeoutSauce):
pass
else:
timeout = TimeoutSauce(connect=timeout, read=timeout)

try:
> resp = conn.urlopen(
method=request.method,
url=url,
body=request.body,
headers=request.headers,
redirect=False,
assert_same_host=False,
preload_content=False,
decode_content=False,
retries=self.max_retries,
timeout=timeout,
chunked=chunked,
)

venv/lib/python3.11/site-packages/requests/adapters.py:564:
_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _
venv/lib/python3.11/site-packages/urllib3/connectionpool.py:843: in urlopen
retries = retries.increment(
_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _

self = Retry(total=0, connect=None, read=False, redirect=None, status=None), method = 'POST', url = '/api/v5/addons/upload/', response = None
error = NameResolutionError("<urllib3.connection.HTTPSConnection object at 0x104bc3ad0>: Failed to resolve 'addons.allizom.org' ([Errno 8] nodename nor servname provided, or not known)")
_pool = <urllib3.connectionpool.HTTPSConnectionPool object at 0x104bc2d50>, _stacktrace = <traceback object at 0x104bc3840>

def increment(
self,
method: str | None = None,
url: str | None = None,
response: BaseHTTPResponse | None = None,
error: Exception | None = None,
_pool: ConnectionPool | None = None,
_stacktrace: TracebackType | None = None,
) -> Self:
"""Return a new Retry object with incremented retry counters.

:param response: A response object, or None, if the server did not
return a response.
:type response: :class:`~urllib3.response.BaseHTTPResponse`
:param Exception error: An error encountered during the request, or
None if the response was received successfully.

:return: A new ``Retry`` object.
"""
if self.total is False and error:
# Disabled, indicate to re-raise the error.
raise reraise(type(error), error, _stacktrace)

total = self.total
if total is not None:
total -= 1

connect = self.connect
read = self.read
redirect = self.redirect
status_count = self.status
other = self.other
cause = "unknown"
status = None
redirect_location = None

if error and self._is_connection_error(error):
# Connect retry?
if connect is False:
raise reraise(type(error), error, _stacktrace)
elif connect is not None:
connect -= 1

elif error and self._is_read_error(error):
# Read retry?
if read is False or method is None or not self._is_method_retryable(method):
raise reraise(type(error), error, _stacktrace)
elif read is not None:
read -= 1

elif error:
# Other retry?
if other is not None:
other -= 1

elif response and response.get_redirect_location():
# Redirect retry?
if redirect is not None:
redirect -= 1
cause = "too many redirects"
response_redirect_location = response.get_redirect_location()
if response_redirect_location:
redirect_location = response_redirect_location
status = response.status

else:
# Incrementing because of a server error like a 500 in
# status_forcelist and the given method is in the allowed_methods
cause = ResponseError.GENERIC_ERROR
if response and response.status:
if status_count is not None:
status_count -= 1
cause = ResponseError.SPECIFIC_ERROR.format(status_code=response.status)
status = response.status

history = self.history + (
RequestHistory(method, url, error, status, redirect_location),
)

new_retry = self.new(
total=total,
connect=connect,
read=read,
redirect=redirect,
status=status_count,
other=other,
history=history,
)

if new_retry.is_exhausted():
reason = error or ResponseError(cause)
> raise MaxRetryError(_pool, url, reason) from reason # type: ignore[arg-type]
E urllib3.exceptions.MaxRetryError: HTTPSConnectionPool(host='addons.allizom.org', port=443): Max retries exceeded with url: /api/v5/addons/upload/ (Caused by NameResolutionError("<urllib3.connection.HTTPSConnection object at 0x104bc3ad0>: Failed to resolve 'addons.allizom.org' ([Errno 8] nodename nor servname provided, or not known)"))

venv/lib/python3.11/site-packages/urllib3/util/retry.py:519: MaxRetryError

During handling of the above exception, another exception occurred:

base_url = 'https://addons.allizom.org', session_auth = 'ldvd5ag27bkfpukx6rn2lcj0yuvakt3v'

@pytest.mark.serial
@pytest.mark.create_session("api_user")
def test_upload_extension_with_put_no_guid_in_request(base_url, session_auth):
"""The PUT method requires a guid to be specified in the request;
if no guid is specified in the url, the request should fail"""
guid = f"random-guid@{reusables.get_random_string(6)}"
# create the addon manifest to be uploaded
manifest = {
**payloads.minimal_manifest,
"name": "PUT-no-guid-in-request-url",
"browser_specific_settings": {"gecko": {"id": guid}},
}
api_helpers.make_addon(manifest)
with open("sample-addons/make-addon.zip", "rb") as file:
> upload = requests.post(
url=f"{base_url}{_upload}",
headers={"Authorization": f"Session {session_auth}"},
files={"upload": file},
data={"channel": "listed"},
)

tests/api_w/test_addon_uploads.py:741:
_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _
venv/lib/python3.11/site-packages/requests/api.py:115: in post
return request("post", url, data=data, json=json, **kwargs)
venv/lib/python3.11/site-packages/requests/api.py:59: in request
return session.request(method=method, url=url, **kwargs)
venv/lib/python3.11/site-packages/requests/sessions.py:589: in request
resp = self.send(prep, **send_kwargs)
venv/lib/python3.11/site-packages/requests/sessions.py:703: in send
r = adapter.send(request, **kwargs)
_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _

self = <requests.adapters.HTTPAdapter object at 0x1040d0390>, request = <PreparedRequest [POST]>, stream = False, timeout = Timeout(connect=None, read=None, total=None), verify = True, cert = None
proxies = OrderedDict()

def send(
self, request, stream=False, timeout=None, verify=True, cert=None, proxies=None
):
"""Sends PreparedRequest object. Returns Response object.

:param request: The :class:`PreparedRequest <PreparedRequest>` being sent.
:param stream: (optional) Whether to stream the request content.
:param timeout: (optional) How long to wait for the server to send
data before giving up, as a float, or a :ref:`(connect timeout,
read timeout) <timeouts>` tuple.
:type timeout: float or tuple or urllib3 Timeout object
:param verify: (optional) Either a boolean, in which case it controls whether
we verify the server's TLS certificate, or a string, in which case it
must be a path to a CA bundle to use
:param cert: (optional) Any user-provided SSL certificate to be trusted.
:param proxies: (optional) The proxies dictionary to apply to the request.
:rtype: requests.Response
"""

try:
conn = self._get_connection(request, verify, proxies=proxies, cert=cert)
except LocationValueError as e:
raise InvalidURL(e, request=request)

self.cert_verify(conn, request.url, verify, cert)
url = self.request_url(request, proxies)
self.add_headers(
request,
stream=stream,
timeout=timeout,
verify=verify,
cert=cert,
proxies=proxies,
)

chunked = not (request.body is None or "Content-Length" in request.headers)

if isinstance(timeout, tuple):
try:
connect, read = timeout
timeout = TimeoutSauce(connect=connect, read=read)
except ValueError:
raise ValueError(
f"Invalid timeout {timeout}. Pass a (connect, read) timeout tuple, "
f"or a single float to set both timeouts to the same value."
)
elif isinstance(timeout, TimeoutSauce):
pass
else:
timeout = TimeoutSauce(connect=timeout, read=timeout)

try:
resp = conn.urlopen(
method=request.method,
url=url,
body=request.body,
headers=request.headers,
redirect=False,
assert_same_host=False,
preload_content=False,
decode_content=False,
retries=self.max_retries,
timeout=timeout,
chunked=chunked,
)

except (ProtocolError, OSError) as err:
raise ConnectionError(err, request=request)

except MaxRetryError as e:
if isinstance(e.reason, ConnectTimeoutError):
# TODO: Remove this in 3.0.0: see #2811
if not isinstance(e.reason, NewConnectionError):
raise ConnectTimeout(e, request=request)

if isinstance(e.reason, ResponseError):
raise RetryError(e, request=request)

if isinstance(e.reason, _ProxyError):
raise ProxyError(e, request=request)

if isinstance(e.reason, _SSLError):
# This branch is for urllib3 v1.22 and later.
raise SSLError(e, request=request)

> raise ConnectionError(e, request=request)
E requests.exceptions.ConnectionError: HTTPSConnectionPool(host='addons.allizom.org', port=443): Max retries exceeded with url: /api/v5/addons/upload/ (Caused by NameResolutionError("<urllib3.connection.HTTPSConnection object at 0x104bc3ad0>: Failed to resolve 'addons.allizom.org' ([Errno 8] nodename nor servname provided, or not known)"))

venv/lib/python3.11/site-packages/requests/adapters.py:597: ConnectionError
------------------------------Captured stdout call------------------------------
Manifest content: {'manifest_version': 2, 'version': '1.0', 'name': 'PUT-no-guid-in-request-url', 'browser_specific_settings': {'gecko': {'id': 'random-guid@cuttjt'}}}
Failed tests/api_w/test_addon_uploads.py::test_upload_extension_with_put_invalid_guid_format 0.01
self = <urllib3.connection.HTTPSConnection object at 0x10414d990>

def _new_conn(self) -> socket.socket:
"""Establish a socket connection and set nodelay settings on it.

:return: New socket connection.
"""
try:
> sock = connection.create_connection(
(self._dns_host, self.port),
self.timeout,
source_address=self.source_address,
socket_options=self.socket_options,
)

venv/lib/python3.11/site-packages/urllib3/connection.py:196:
_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _
venv/lib/python3.11/site-packages/urllib3/util/connection.py:60: in create_connection
for res in socket.getaddrinfo(host, port, family, socket.SOCK_STREAM):
_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _

host = 'addons.allizom.org', port = 443, family = <AddressFamily.AF_UNSPEC: 0>, type = <SocketKind.SOCK_STREAM: 1>, proto = 0, flags = 0

def getaddrinfo(host, port, family=0, type=0, proto=0, flags=0):
"""Resolve host and port into list of address info entries.

Translate the host/port argument into a sequence of 5-tuples that contain
all the necessary arguments for creating a socket connected to that service.
host is a domain name, a string representation of an IPv4/v6 address or
None. port is a string service name such as 'http', a numeric port number or
None. By passing None as the value of host and port, you can pass NULL to
the underlying C API.

The family, type and proto arguments can be optionally specified in order to
narrow the list of addresses returned. Passing zero as a value for each of
these arguments selects the full range of results.
"""
# We override this function since we want to translate the numeric family
# and socket type values to enum constants.
addrlist = []
> for res in _socket.getaddrinfo(host, port, family, type, proto, flags):
E socket.gaierror: [Errno 8] nodename nor servname provided, or not known

/Library/Frameworks/Python.framework/Versions/3.11/lib/python3.11/socket.py:962: gaierror

The above exception was the direct cause of the following exception:

self = <urllib3.connectionpool.HTTPSConnectionPool object at 0x103c61090>, method = 'POST', url = '/api/v5/addons/upload/'
body = b'--81baaa755a854ce297f0912303b261ec\r\nContent-Disposition: form-data; name="channel"\r\n\r\nlisted\r\n--81baaa755a85...5\x06\x00\x00\x00\x00\x01\x00\x01\x00;\x00\x00\x00\xb5\x00\x00\x00\x00\x00\r\n--81baaa755a854ce297f0912303b261ec--\r\n'
headers = {'User-Agent': 'python-requests/2.32.0', 'Accept-Encoding': 'gzip, deflate', 'Accept': '*/*', 'Connection': 'keep-aliv...j0yuvakt3v', 'Content-Length': '508', 'Content-Type': 'multipart/form-data; boundary=81baaa755a854ce297f0912303b261ec'}
retries = Retry(total=0, connect=None, read=False, redirect=None, status=None), redirect = False, assert_same_host = False, timeout = Timeout(connect=None, read=None, total=None), pool_timeout = None
release_conn = False, chunked = False, body_pos = None, preload_content = False, decode_content = False, response_kw = {}
parsed_url = Url(scheme=None, auth=None, host=None, port=None, path='/api/v5/addons/upload/', query=None, fragment=None), destination_scheme = None, conn = None, release_this_conn = True
http_tunnel_required = False, err = None, clean_exit = False

def urlopen( # type: ignore[override]
self,
method: str,
url: str,
body: _TYPE_BODY | None = None,
headers: typing.Mapping[str, str] | None = None,
retries: Retry | bool | int | None = None,
redirect: bool = True,
assert_same_host: bool = True,
timeout: _TYPE_TIMEOUT = _DEFAULT_TIMEOUT,
pool_timeout: int | None = None,
release_conn: bool | None = None,
chunked: bool = False,
body_pos: _TYPE_BODY_POSITION | None = None,
preload_content: bool = True,
decode_content: bool = True,
**response_kw: typing.Any,
) -> BaseHTTPResponse:
"""
Get a connection from the pool and perform an HTTP request. This is the
lowest level call for making a request, so you'll need to specify all
the raw details.

.. note::

More commonly, it's appropriate to use a convenience method
such as :meth:`request`.

.. note::

`release_conn` will only behave as expected if
`preload_content=False` because we want to make
`preload_content=False` the default behaviour someday soon without
breaking backwards compatibility.

:param method:
HTTP request method (such as GET, POST, PUT, etc.)

:param url:
The URL to perform the request on.

:param body:
Data to send in the request body, either :class:`str`, :class:`bytes`,
an iterable of :class:`str`/:class:`bytes`, or a file-like object.

:param headers:
Dictionary of custom headers to send, such as User-Agent,
If-None-Match, etc. If None, pool headers are used. If provided,
these headers completely replace any pool-specific headers.

:param retries:
Configure the number of retries to allow before raising a
:class:`~urllib3.exceptions.MaxRetryError` exception.

If ``None`` (default) will retry 3 times, see ``Retry.DEFAULT``. Pass a
:class:`~urllib3.util.retry.Retry` object for fine-grained control
over different types of retries.
Pass an integer number to retry connection errors that many times,
but no other types of errors. Pass zero to never retry.

If ``False``, then retries are disabled and any exception is raised
immediately. Also, instead of raising a MaxRetryError on redirects,
the redirect response will be returned.

:type retries: :class:`~urllib3.util.retry.Retry`, False, or an int.

:param redirect:
If True, automatically handle redirects (status codes 301, 302,
303, 307, 308). Each redirect counts as a retry. Disabling retries
will disable redirect, too.

:param assert_same_host:
If ``True``, will make sure that the host of the pool requests is
consistent else will raise HostChangedError. When ``False``, you can
use the pool on an HTTP proxy and request foreign hosts.

:param timeout:
If specified, overrides the default timeout for this one
request. It may be a float (in seconds) or an instance of
:class:`urllib3.util.Timeout`.

:param pool_timeout:
If set and the pool is set to block=True, then this method will
block for ``pool_timeout`` seconds and raise EmptyPoolError if no
connection is available within the time period.

:param bool preload_content:
If True, the response's body will be preloaded into memory.

:param bool decode_content:
If True, will attempt to decode the body based on the
'content-encoding' header.

:param release_conn:
If False, then the urlopen call will not release the connection
back into the pool once a response is received (but will release if
you read the entire contents of the response such as when
`preload_content=True`). This is useful if you're not preloading
the response's content immediately. You will need to call
``r.release_conn()`` on the response ``r`` to return the connection
back into the pool. If None, it takes the value of ``preload_content``
which defaults to ``True``.

:param bool chunked:
If True, urllib3 will send the body using chunked transfer
encoding. Otherwise, urllib3 will send the body using the standard
content-length form. Defaults to False.

:param int body_pos:
Position to seek to in file-like body in the event of a retry or
redirect. Typically this won't need to be set because urllib3 will
auto-populate the value when needed.
"""
parsed_url = parse_url(url)
destination_scheme = parsed_url.scheme

if headers is None:
headers = self.headers

if not isinstance(retries, Retry):
retries = Retry.from_int(retries, redirect=redirect, default=self.retries)

if release_conn is None:
release_conn = preload_content

# Check host
if assert_same_host and not self.is_same_host(url):
raise HostChangedError(self, url, retries)

# Ensure that the URL we're connecting to is properly encoded
if url.startswith("/"):
url = to_str(_encode_target(url))
else:
url = to_str(parsed_url.url)

conn = None

# Track whether `conn` needs to be released before
# returning/raising/recursing. Update this variable if necessary, and
# leave `release_conn` constant throughout the function. That way, if
# the function recurses, the original value of `release_conn` will be
# passed down into the recursive call, and its value will be respected.
#
# See issue #651 [1] for details.
#
# [1] <https://github.com/urllib3/urllib3/issues/651>
release_this_conn = release_conn

http_tunnel_required = connection_requires_http_tunnel(
self.proxy, self.proxy_config, destination_scheme
)

# Merge the proxy headers. Only done when not using HTTP CONNECT. We
# have to copy the headers dict so we can safely change it without those
# changes being reflected in anyone else's copy.
if not http_tunnel_required:
headers = headers.copy() # type: ignore[attr-defined]
headers.update(self.proxy_headers) # type: ignore[union-attr]

# Must keep the exception bound to a separate variable or else Python 3
# complains about UnboundLocalError.
err = None

# Keep track of whether we cleanly exited the except block. This
# ensures we do proper cleanup in finally.
clean_exit = False

# Rewind body position, if needed. Record current position
# for future rewinds in the event of a redirect/retry.
body_pos = set_file_position(body, body_pos)

try:
# Request a connection from the queue.
timeout_obj = self._get_timeout(timeout)
conn = self._get_conn(timeout=pool_timeout)

conn.timeout = timeout_obj.connect_timeout # type: ignore[assignment]

# Is this a closed/new connection that requires CONNECT tunnelling?
if self.proxy is not None and http_tunnel_required and conn.is_closed:
try:
self._prepare_proxy(conn)
except (BaseSSLError, OSError, SocketTimeout) as e:
self._raise_timeout(
err=e, url=self.proxy.url, timeout_value=conn.timeout
)
raise

# If we're going to release the connection in ``finally:``, then
# the response doesn't need to know about the connection. Otherwise
# it will also try to release it and we'll have a double-release
# mess.
response_conn = conn if not release_conn else None

# Make the request on the HTTPConnection object
> response = self._make_request(
conn,
method,
url,
timeout=timeout_obj,
body=body,
headers=headers,
chunked=chunked,
retries=retries,
response_conn=response_conn,
preload_content=preload_content,
decode_content=decode_content,
**response_kw,
)

venv/lib/python3.11/site-packages/urllib3/connectionpool.py:789:
_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _
venv/lib/python3.11/site-packages/urllib3/connectionpool.py:490: in _make_request
raise new_e
venv/lib/python3.11/site-packages/urllib3/connectionpool.py:466: in _make_request
self._validate_conn(conn)
venv/lib/python3.11/site-packages/urllib3/connectionpool.py:1095: in _validate_conn
conn.connect()
venv/lib/python3.11/site-packages/urllib3/connection.py:615: in connect
self.sock = sock = self._new_conn()
_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _

self = <urllib3.connection.HTTPSConnection object at 0x10414d990>

def _new_conn(self) -> socket.socket:
"""Establish a socket connection and set nodelay settings on it.

:return: New socket connection.
"""
try:
sock = connection.create_connection(
(self._dns_host, self.port),
self.timeout,
source_address=self.source_address,
socket_options=self.socket_options,
)
except socket.gaierror as e:
> raise NameResolutionError(self.host, self, e) from e
E urllib3.exceptions.NameResolutionError: <urllib3.connection.HTTPSConnection object at 0x10414d990>: Failed to resolve 'addons.allizom.org' ([Errno 8] nodename nor servname provided, or not known)

venv/lib/python3.11/site-packages/urllib3/connection.py:203: NameResolutionError

The above exception was the direct cause of the following exception:

self = <requests.adapters.HTTPAdapter object at 0x103c61590>, request = <PreparedRequest [POST]>, stream = False, timeout = Timeout(connect=None, read=None, total=None), verify = True, cert = None
proxies = OrderedDict()

def send(
self, request, stream=False, timeout=None, verify=True, cert=None, proxies=None
):
"""Sends PreparedRequest object. Returns Response object.

:param request: The :class:`PreparedRequest <PreparedRequest>` being sent.
:param stream: (optional) Whether to stream the request content.
:param timeout: (optional) How long to wait for the server to send
data before giving up, as a float, or a :ref:`(connect timeout,
read timeout) <timeouts>` tuple.
:type timeout: float or tuple or urllib3 Timeout object
:param verify: (optional) Either a boolean, in which case it controls whether
we verify the server's TLS certificate, or a string, in which case it
must be a path to a CA bundle to use
:param cert: (optional) Any user-provided SSL certificate to be trusted.
:param proxies: (optional) The proxies dictionary to apply to the request.
:rtype: requests.Response
"""

try:
conn = self._get_connection(request, verify, proxies=proxies, cert=cert)
except LocationValueError as e:
raise InvalidURL(e, request=request)

self.cert_verify(conn, request.url, verify, cert)
url = self.request_url(request, proxies)
self.add_headers(
request,
stream=stream,
timeout=timeout,
verify=verify,
cert=cert,
proxies=proxies,
)

chunked = not (request.body is None or "Content-Length" in request.headers)

if isinstance(timeout, tuple):
try:
connect, read = timeout
timeout = TimeoutSauce(connect=connect, read=read)
except ValueError:
raise ValueError(
f"Invalid timeout {timeout}. Pass a (connect, read) timeout tuple, "
f"or a single float to set both timeouts to the same value."
)
elif isinstance(timeout, TimeoutSauce):
pass
else:
timeout = TimeoutSauce(connect=timeout, read=timeout)

try:
> resp = conn.urlopen(
method=request.method,
url=url,
body=request.body,
headers=request.headers,
redirect=False,
assert_same_host=False,
preload_content=False,
decode_content=False,
retries=self.max_retries,
timeout=timeout,
chunked=chunked,
)

venv/lib/python3.11/site-packages/requests/adapters.py:564:
_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _
venv/lib/python3.11/site-packages/urllib3/connectionpool.py:843: in urlopen
retries = retries.increment(
_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _

self = Retry(total=0, connect=None, read=False, redirect=None, status=None), method = 'POST', url = '/api/v5/addons/upload/', response = None
error = NameResolutionError("<urllib3.connection.HTTPSConnection object at 0x10414d990>: Failed to resolve 'addons.allizom.org' ([Errno 8] nodename nor servname provided, or not known)")
_pool = <urllib3.connectionpool.HTTPSConnectionPool object at 0x103c61090>, _stacktrace = <traceback object at 0x10414e640>

def increment(
self,
method: str | None = None,
url: str | None = None,
response: BaseHTTPResponse | None = None,
error: Exception | None = None,
_pool: ConnectionPool | None = None,
_stacktrace: TracebackType | None = None,
) -> Self:
"""Return a new Retry object with incremented retry counters.

:param response: A response object, or None, if the server did not
return a response.
:type response: :class:`~urllib3.response.BaseHTTPResponse`
:param Exception error: An error encountered during the request, or
None if the response was received successfully.

:return: A new ``Retry`` object.
"""
if self.total is False and error:
# Disabled, indicate to re-raise the error.
raise reraise(type(error), error, _stacktrace)

total = self.total
if total is not None:
total -= 1

connect = self.connect
read = self.read
redirect = self.redirect
status_count = self.status
other = self.other
cause = "unknown"
status = None
redirect_location = None

if error and self._is_connection_error(error):
# Connect retry?
if connect is False:
raise reraise(type(error), error, _stacktrace)
elif connect is not None:
connect -= 1

elif error and self._is_read_error(error):
# Read retry?
if read is False or method is None or not self._is_method_retryable(method):
raise reraise(type(error), error, _stacktrace)
elif read is not None:
read -= 1

elif error:
# Other retry?
if other is not None:
other -= 1

elif response and response.get_redirect_location():
# Redirect retry?
if redirect is not None:
redirect -= 1
cause = "too many redirects"
response_redirect_location = response.get_redirect_location()
if response_redirect_location:
redirect_location = response_redirect_location
status = response.status

else:
# Incrementing because of a server error like a 500 in
# status_forcelist and the given method is in the allowed_methods
cause = ResponseError.GENERIC_ERROR
if response and response.status:
if status_count is not None:
status_count -= 1
cause = ResponseError.SPECIFIC_ERROR.format(status_code=response.status)
status = response.status

history = self.history + (
RequestHistory(method, url, error, status, redirect_location),
)

new_retry = self.new(
total=total,
connect=connect,
read=read,
redirect=redirect,
status=status_count,
other=other,
history=history,
)

if new_retry.is_exhausted():
reason = error or ResponseError(cause)
> raise MaxRetryError(_pool, url, reason) from reason # type: ignore[arg-type]
E urllib3.exceptions.MaxRetryError: HTTPSConnectionPool(host='addons.allizom.org', port=443): Max retries exceeded with url: /api/v5/addons/upload/ (Caused by NameResolutionError("<urllib3.connection.HTTPSConnection object at 0x10414d990>: Failed to resolve 'addons.allizom.org' ([Errno 8] nodename nor servname provided, or not known)"))

venv/lib/python3.11/site-packages/urllib3/util/retry.py:519: MaxRetryError

During handling of the above exception, another exception occurred:

base_url = 'https://addons.allizom.org', session_auth = 'ldvd5ag27bkfpukx6rn2lcj0yuvakt3v'

@pytest.mark.serial
@pytest.mark.create_session("api_user")
def test_upload_extension_with_put_invalid_guid_format(base_url, session_auth):
"""Uploading an addon with an invalid guid format should fail the PUT request"""
guid = f"invalid-{reusables.get_random_string(6)}" # creates an invalid guid
manifest = {
**payloads.minimal_manifest,
"name": "Invalid guid format",
"browser_specific_settings": {"gecko": {"id": guid}},
}
api_helpers.make_addon(manifest)
with open("sample-addons/make-addon.zip", "rb") as file:
> upload = requests.post(
url=f"{base_url}{_upload}",
headers={"Authorization": f"Session {session_auth}"},
files={"upload": file},
data={"channel": "listed"},
)

tests/api_w/test_addon_uploads.py:782:
_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _
venv/lib/python3.11/site-packages/requests/api.py:115: in post
return request("post", url, data=data, json=json, **kwargs)
venv/lib/python3.11/site-packages/requests/api.py:59: in request
return session.request(method=method, url=url, **kwargs)
venv/lib/python3.11/site-packages/requests/sessions.py:589: in request
resp = self.send(prep, **send_kwargs)
venv/lib/python3.11/site-packages/requests/sessions.py:703: in send
r = adapter.send(request, **kwargs)
_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _

self = <requests.adapters.HTTPAdapter object at 0x103c61590>, request = <PreparedRequest [POST]>, stream = False, timeout = Timeout(connect=None, read=None, total=None), verify = True, cert = None
proxies = OrderedDict()

def send(
self, request, stream=False, timeout=None, verify=True, cert=None, proxies=None
):
"""Sends PreparedRequest object. Returns Response object.

:param request: The :class:`PreparedRequest <PreparedRequest>` being sent.
:param stream: (optional) Whether to stream the request content.
:param timeout: (optional) How long to wait for the server to send
data before giving up, as a float, or a :ref:`(connect timeout,
read timeout) <timeouts>` tuple.
:type timeout: float or tuple or urllib3 Timeout object
:param verify: (optional) Either a boolean, in which case it controls whether
we verify the server's TLS certificate, or a string, in which case it
must be a path to a CA bundle to use
:param cert: (optional) Any user-provided SSL certificate to be trusted.
:param proxies: (optional) The proxies dictionary to apply to the request.
:rtype: requests.Response
"""

try:
conn = self._get_connection(request, verify, proxies=proxies, cert=cert)
except LocationValueError as e:
raise InvalidURL(e, request=request)

self.cert_verify(conn, request.url, verify, cert)
url = self.request_url(request, proxies)
self.add_headers(
request,
stream=stream,
timeout=timeout,
verify=verify,
cert=cert,
proxies=proxies,
)

chunked = not (request.body is None or "Content-Length" in request.headers)

if isinstance(timeout, tuple):
try:
connect, read = timeout
timeout = TimeoutSauce(connect=connect, read=read)
except ValueError:
raise ValueError(
f"Invalid timeout {timeout}. Pass a (connect, read) timeout tuple, "
f"or a single float to set both timeouts to the same value."
)
elif isinstance(timeout, TimeoutSauce):
pass
else:
timeout = TimeoutSauce(connect=timeout, read=timeout)

try:
resp = conn.urlopen(
method=request.method,
url=url,
body=request.body,
headers=request.headers,
redirect=False,
assert_same_host=False,
preload_content=False,
decode_content=False,
retries=self.max_retries,
timeout=timeout,
chunked=chunked,
)

except (ProtocolError, OSError) as err:
raise ConnectionError(err, request=request)

except MaxRetryError as e:
if isinstance(e.reason, ConnectTimeoutError):
# TODO: Remove this in 3.0.0: see #2811
if not isinstance(e.reason, NewConnectionError):
raise ConnectTimeout(e, request=request)

if isinstance(e.reason, ResponseError):
raise RetryError(e, request=request)

if isinstance(e.reason, _ProxyError):
raise ProxyError(e, request=request)

if isinstance(e.reason, _SSLError):
# This branch is for urllib3 v1.22 and later.
raise SSLError(e, request=request)

> raise ConnectionError(e, request=request)
E requests.exceptions.ConnectionError: HTTPSConnectionPool(host='addons.allizom.org', port=443): Max retries exceeded with url: /api/v5/addons/upload/ (Caused by NameResolutionError("<urllib3.connection.HTTPSConnection object at 0x10414d990>: Failed to resolve 'addons.allizom.org' ([Errno 8] nodename nor servname provided, or not known)"))

venv/lib/python3.11/site-packages/requests/adapters.py:597: ConnectionError
------------------------------Captured stdout call------------------------------
Manifest content: {'manifest_version': 2, 'version': '1.0', 'name': 'Invalid guid format', 'browser_specific_settings': {'gecko': {'id': 'invalid-mlvlue'}}}
Failed tests/api_w/test_addon_uploads.py::test_upload_extension_default_locale_has_no_translations 0.00
self = <urllib3.connection.HTTPSConnection object at 0x103756f90>

def _new_conn(self) -> socket.socket:
"""Establish a socket connection and set nodelay settings on it.

:return: New socket connection.
"""
try:
> sock = connection.create_connection(
(self._dns_host, self.port),
self.timeout,
source_address=self.source_address,
socket_options=self.socket_options,
)

venv/lib/python3.11/site-packages/urllib3/connection.py:196:
_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _
venv/lib/python3.11/site-packages/urllib3/util/connection.py:60: in create_connection
for res in socket.getaddrinfo(host, port, family, socket.SOCK_STREAM):
_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _

host = 'addons.allizom.org', port = 443, family = <AddressFamily.AF_UNSPEC: 0>, type = <SocketKind.SOCK_STREAM: 1>, proto = 0, flags = 0

def getaddrinfo(host, port, family=0, type=0, proto=0, flags=0):
"""Resolve host and port into list of address info entries.

Translate the host/port argument into a sequence of 5-tuples that contain
all the necessary arguments for creating a socket connected to that service.
host is a domain name, a string representation of an IPv4/v6 address or
None. port is a string service name such as 'http', a numeric port number or
None. By passing None as the value of host and port, you can pass NULL to
the underlying C API.

The family, type and proto arguments can be optionally specified in order to
narrow the list of addresses returned. Passing zero as a value for each of
these arguments selects the full range of results.
"""
# We override this function since we want to translate the numeric family
# and socket type values to enum constants.
addrlist = []
> for res in _socket.getaddrinfo(host, port, family, type, proto, flags):
E socket.gaierror: [Errno 8] nodename nor servname provided, or not known

/Library/Frameworks/Python.framework/Versions/3.11/lib/python3.11/socket.py:962: gaierror

The above exception was the direct cause of the following exception:

self = <urllib3.connectionpool.HTTPSConnectionPool object at 0x103756e90>, method = 'POST', url = '/api/v5/addons/upload/'
body = b'--0bd2b77e586b6c95d4d95dbd55c1a2a3\r\nContent-Disposition: form-data; name="channel"\r\n\r\nlisted\r\n--0bd2b77e586b...05\x06\x00\x00\x00\x00\t\x00\t\x00\xe8\x02\x00\x00\xe9\x08\x01\x00\x00\x00\r\n--0bd2b77e586b6c95d4d95dbd55c1a2a3--\r\n'
headers = {'User-Agent': 'python-requests/2.32.0', 'Accept-Encoding': 'gzip, deflate', 'Accept': '*/*', 'Connection': 'keep-aliv...yuvakt3v', 'Content-Length': '68832', 'Content-Type': 'multipart/form-data; boundary=0bd2b77e586b6c95d4d95dbd55c1a2a3'}
retries = Retry(total=0, connect=None, read=False, redirect=None, status=None), redirect = False, assert_same_host = False, timeout = Timeout(connect=None, read=None, total=None), pool_timeout = None
release_conn = False, chunked = False, body_pos = None, preload_content = False, decode_content = False, response_kw = {}
parsed_url = Url(scheme=None, auth=None, host=None, port=None, path='/api/v5/addons/upload/', query=None, fragment=None), destination_scheme = None, conn = None, release_this_conn = True
http_tunnel_required = False, err = None, clean_exit = False

def urlopen( # type: ignore[override]
self,
method: str,
url: str,
body: _TYPE_BODY | None = None,
headers: typing.Mapping[str, str] | None = None,
retries: Retry | bool | int | None = None,
redirect: bool = True,
assert_same_host: bool = True,
timeout: _TYPE_TIMEOUT = _DEFAULT_TIMEOUT,
pool_timeout: int | None = None,
release_conn: bool | None = None,
chunked: bool = False,
body_pos: _TYPE_BODY_POSITION | None = None,
preload_content: bool = True,
decode_content: bool = True,
**response_kw: typing.Any,
) -> BaseHTTPResponse:
"""
Get a connection from the pool and perform an HTTP request. This is the
lowest level call for making a request, so you'll need to specify all
the raw details.

.. note::

More commonly, it's appropriate to use a convenience method
such as :meth:`request`.

.. note::

`release_conn` will only behave as expected if
`preload_content=False` because we want to make
`preload_content=False` the default behaviour someday soon without
breaking backwards compatibility.

:param method:
HTTP request method (such as GET, POST, PUT, etc.)

:param url:
The URL to perform the request on.

:param body:
Data to send in the request body, either :class:`str`, :class:`bytes`,
an iterable of :class:`str`/:class:`bytes`, or a file-like object.

:param headers:
Dictionary of custom headers to send, such as User-Agent,
If-None-Match, etc. If None, pool headers are used. If provided,
these headers completely replace any pool-specific headers.

:param retries:
Configure the number of retries to allow before raising a
:class:`~urllib3.exceptions.MaxRetryError` exception.

If ``None`` (default) will retry 3 times, see ``Retry.DEFAULT``. Pass a
:class:`~urllib3.util.retry.Retry` object for fine-grained control
over different types of retries.
Pass an integer number to retry connection errors that many times,
but no other types of errors. Pass zero to never retry.

If ``False``, then retries are disabled and any exception is raised
immediately. Also, instead of raising a MaxRetryError on redirects,
the redirect response will be returned.

:type retries: :class:`~urllib3.util.retry.Retry`, False, or an int.

:param redirect:
If True, automatically handle redirects (status codes 301, 302,
303, 307, 308). Each redirect counts as a retry. Disabling retries
will disable redirect, too.

:param assert_same_host:
If ``True``, will make sure that the host of the pool requests is
consistent else will raise HostChangedError. When ``False``, you can
use the pool on an HTTP proxy and request foreign hosts.

:param timeout:
If specified, overrides the default timeout for this one
request. It may be a float (in seconds) or an instance of
:class:`urllib3.util.Timeout`.

:param pool_timeout:
If set and the pool is set to block=True, then this method will
block for ``pool_timeout`` seconds and raise EmptyPoolError if no
connection is available within the time period.

:param bool preload_content:
If True, the response's body will be preloaded into memory.

:param bool decode_content:
If True, will attempt to decode the body based on the
'content-encoding' header.

:param release_conn:
If False, then the urlopen call will not release the connection
back into the pool once a response is received (but will release if
you read the entire contents of the response such as when
`preload_content=True`). This is useful if you're not preloading
the response's content immediately. You will need to call
``r.release_conn()`` on the response ``r`` to return the connection
back into the pool. If None, it takes the value of ``preload_content``
which defaults to ``True``.

:param bool chunked:
If True, urllib3 will send the body using chunked transfer
encoding. Otherwise, urllib3 will send the body using the standard
content-length form. Defaults to False.

:param int body_pos:
Position to seek to in file-like body in the event of a retry or
redirect. Typically this won't need to be set because urllib3 will
auto-populate the value when needed.
"""
parsed_url = parse_url(url)
destination_scheme = parsed_url.scheme

if headers is None:
headers = self.headers

if not isinstance(retries, Retry):
retries = Retry.from_int(retries, redirect=redirect, default=self.retries)

if release_conn is None:
release_conn = preload_content

# Check host
if assert_same_host and not self.is_same_host(url):
raise HostChangedError(self, url, retries)

# Ensure that the URL we're connecting to is properly encoded
if url.startswith("/"):
url = to_str(_encode_target(url))
else:
url = to_str(parsed_url.url)

conn = None

# Track whether `conn` needs to be released before
# returning/raising/recursing. Update this variable if necessary, and
# leave `release_conn` constant throughout the function. That way, if
# the function recurses, the original value of `release_conn` will be
# passed down into the recursive call, and its value will be respected.
#
# See issue #651 [1] for details.
#
# [1] <https://github.com/urllib3/urllib3/issues/651>
release_this_conn = release_conn

http_tunnel_required = connection_requires_http_tunnel(
self.proxy, self.proxy_config, destination_scheme
)

# Merge the proxy headers. Only done when not using HTTP CONNECT. We
# have to copy the headers dict so we can safely change it without those
# changes being reflected in anyone else's copy.
if not http_tunnel_required:
headers = headers.copy() # type: ignore[attr-defined]
headers.update(self.proxy_headers) # type: ignore[union-attr]

# Must keep the exception bound to a separate variable or else Python 3
# complains about UnboundLocalError.
err = None

# Keep track of whether we cleanly exited the except block. This
# ensures we do proper cleanup in finally.
clean_exit = False

# Rewind body position, if needed. Record current position
# for future rewinds in the event of a redirect/retry.
body_pos = set_file_position(body, body_pos)

try:
# Request a connection from the queue.
timeout_obj = self._get_timeout(timeout)
conn = self._get_conn(timeout=pool_timeout)

conn.timeout = timeout_obj.connect_timeout # type: ignore[assignment]

# Is this a closed/new connection that requires CONNECT tunnelling?
if self.proxy is not None and http_tunnel_required and conn.is_closed:
try:
self._prepare_proxy(conn)
except (BaseSSLError, OSError, SocketTimeout) as e:
self._raise_timeout(
err=e, url=self.proxy.url, timeout_value=conn.timeout
)
raise

# If we're going to release the connection in ``finally:``, then
# the response doesn't need to know about the connection. Otherwise
# it will also try to release it and we'll have a double-release
# mess.
response_conn = conn if not release_conn else None

# Make the request on the HTTPConnection object
> response = self._make_request(
conn,
method,
url,
timeout=timeout_obj,
body=body,
headers=headers,
chunked=chunked,
retries=retries,
response_conn=response_conn,
preload_content=preload_content,
decode_content=decode_content,
**response_kw,
)

venv/lib/python3.11/site-packages/urllib3/connectionpool.py:789:
_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _
venv/lib/python3.11/site-packages/urllib3/connectionpool.py:490: in _make_request
raise new_e
venv/lib/python3.11/site-packages/urllib3/connectionpool.py:466: in _make_request
self._validate_conn(conn)
venv/lib/python3.11/site-packages/urllib3/connectionpool.py:1095: in _validate_conn
conn.connect()
venv/lib/python3.11/site-packages/urllib3/connection.py:615: in connect
self.sock = sock = self._new_conn()
_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _

self = <urllib3.connection.HTTPSConnection object at 0x103756f90>

def _new_conn(self) -> socket.socket:
"""Establish a socket connection and set nodelay settings on it.

:return: New socket connection.
"""
try:
sock = connection.create_connection(
(self._dns_host, self.port),
self.timeout,
source_address=self.source_address,
socket_options=self.socket_options,
)
except socket.gaierror as e:
> raise NameResolutionError(self.host, self, e) from e
E urllib3.exceptions.NameResolutionError: <urllib3.connection.HTTPSConnection object at 0x103756f90>: Failed to resolve 'addons.allizom.org' ([Errno 8] nodename nor servname provided, or not known)

venv/lib/python3.11/site-packages/urllib3/connection.py:203: NameResolutionError

The above exception was the direct cause of the following exception:

self = <requests.adapters.HTTPAdapter object at 0x103b3ba10>, request = <PreparedRequest [POST]>, stream = False, timeout = Timeout(connect=None, read=None, total=None), verify = True, cert = None
proxies = OrderedDict()

def send(
self, request, stream=False, timeout=None, verify=True, cert=None, proxies=None
):
"""Sends PreparedRequest object. Returns Response object.

:param request: The :class:`PreparedRequest <PreparedRequest>` being sent.
:param stream: (optional) Whether to stream the request content.
:param timeout: (optional) How long to wait for the server to send
data before giving up, as a float, or a :ref:`(connect timeout,
read timeout) <timeouts>` tuple.
:type timeout: float or tuple or urllib3 Timeout object
:param verify: (optional) Either a boolean, in which case it controls whether
we verify the server's TLS certificate, or a string, in which case it
must be a path to a CA bundle to use
:param cert: (optional) Any user-provided SSL certificate to be trusted.
:param proxies: (optional) The proxies dictionary to apply to the request.
:rtype: requests.Response
"""

try:
conn = self._get_connection(request, verify, proxies=proxies, cert=cert)
except LocationValueError as e:
raise InvalidURL(e, request=request)

self.cert_verify(conn, request.url, verify, cert)
url = self.request_url(request, proxies)
self.add_headers(
request,
stream=stream,
timeout=timeout,
verify=verify,
cert=cert,
proxies=proxies,
)

chunked = not (request.body is None or "Content-Length" in request.headers)

if isinstance(timeout, tuple):
try:
connect, read = timeout
timeout = TimeoutSauce(connect=connect, read=read)
except ValueError:
raise ValueError(
f"Invalid timeout {timeout}. Pass a (connect, read) timeout tuple, "
f"or a single float to set both timeouts to the same value."
)
elif isinstance(timeout, TimeoutSauce):
pass
else:
timeout = TimeoutSauce(connect=timeout, read=timeout)

try:
> resp = conn.urlopen(
method=request.method,
url=url,
body=request.body,
headers=request.headers,
redirect=False,
assert_same_host=False,
preload_content=False,
decode_content=False,
retries=self.max_retries,
timeout=timeout,
chunked=chunked,
)

venv/lib/python3.11/site-packages/requests/adapters.py:564:
_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _
venv/lib/python3.11/site-packages/urllib3/connectionpool.py:843: in urlopen
retries = retries.increment(
_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _

self = Retry(total=0, connect=None, read=False, redirect=None, status=None), method = 'POST', url = '/api/v5/addons/upload/', response = None
error = NameResolutionError("<urllib3.connection.HTTPSConnection object at 0x103756f90>: Failed to resolve 'addons.allizom.org' ([Errno 8] nodename nor servname provided, or not known)")
_pool = <urllib3.connectionpool.HTTPSConnectionPool object at 0x103756e90>, _stacktrace = <traceback object at 0x1037553c0>

def increment(
self,
method: str | None = None,
url: str | None = None,
response: BaseHTTPResponse | None = None,
error: Exception | None = None,
_pool: ConnectionPool | None = None,
_stacktrace: TracebackType | None = None,
) -> Self:
"""Return a new Retry object with incremented retry counters.

:param response: A response object, or None, if the server did not
return a response.
:type response: :class:`~urllib3.response.BaseHTTPResponse`
:param Exception error: An error encountered during the request, or
None if the response was received successfully.

:return: A new ``Retry`` object.
"""
if self.total is False and error:
# Disabled, indicate to re-raise the error.
raise reraise(type(error), error, _stacktrace)

total = self.total
if total is not None:
total -= 1

connect = self.connect
read = self.read
redirect = self.redirect
status_count = self.status
other = self.other
cause = "unknown"
status = None
redirect_location = None

if error and self._is_connection_error(error):
# Connect retry?
if connect is False:
raise reraise(type(error), error, _stacktrace)
elif connect is not None:
connect -= 1

elif error and self._is_read_error(error):
# Read retry?
if read is False or method is None or not self._is_method_retryable(method):
raise reraise(type(error), error, _stacktrace)
elif read is not None:
read -= 1

elif error:
# Other retry?
if other is not None:
other -= 1

elif response and response.get_redirect_location():
# Redirect retry?
if redirect is not None:
redirect -= 1
cause = "too many redirects"
response_redirect_location = response.get_redirect_location()
if response_redirect_location:
redirect_location = response_redirect_location
status = response.status

else:
# Incrementing because of a server error like a 500 in
# status_forcelist and the given method is in the allowed_methods
cause = ResponseError.GENERIC_ERROR
if response and response.status:
if status_count is not None:
status_count -= 1
cause = ResponseError.SPECIFIC_ERROR.format(status_code=response.status)
status = response.status

history = self.history + (
RequestHistory(method, url, error, status, redirect_location),
)

new_retry = self.new(
total=total,
connect=connect,
read=read,
redirect=redirect,
status=status_count,
other=other,
history=history,
)

if new_retry.is_exhausted():
reason = error or ResponseError(cause)
> raise MaxRetryError(_pool, url, reason) from reason # type: ignore[arg-type]
E urllib3.exceptions.MaxRetryError: HTTPSConnectionPool(host='addons.allizom.org', port=443): Max retries exceeded with url: /api/v5/addons/upload/ (Caused by NameResolutionError("<urllib3.connection.HTTPSConnection object at 0x103756f90>: Failed to resolve 'addons.allizom.org' ([Errno 8] nodename nor servname provided, or not known)"))

venv/lib/python3.11/site-packages/urllib3/util/retry.py:519: MaxRetryError

During handling of the above exception, another exception occurred:

base_url = 'https://addons.allizom.org', session_auth = 'ldvd5ag27bkfpukx6rn2lcj0yuvakt3v'

@pytest.mark.serial
@pytest.mark.create_session("api_user")
def test_upload_extension_default_locale_has_no_translations(base_url, session_auth):
"""Try to upload an addon while setting a 'default_locale' for which there are no
available translations in the mandatory fields, i.e. 'name' and 'summary'"""
with open("sample-addons/localizations.xpi", "rb") as file:
> upload = requests.post(
url=f"{base_url}{_upload}",
headers={"Authorization": f"Session {session_auth}"},
files={"upload": file},
data={"channel": "listed"},
)

tests/api_w/test_addon_uploads.py:825:
_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _
venv/lib/python3.11/site-packages/requests/api.py:115: in post
return request("post", url, data=data, json=json, **kwargs)
venv/lib/python3.11/site-packages/requests/api.py:59: in request
return session.request(method=method, url=url, **kwargs)
venv/lib/python3.11/site-packages/requests/sessions.py:589: in request
resp = self.send(prep, **send_kwargs)
venv/lib/python3.11/site-packages/requests/sessions.py:703: in send
r = adapter.send(request, **kwargs)
_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _

self = <requests.adapters.HTTPAdapter object at 0x103b3ba10>, request = <PreparedRequest [POST]>, stream = False, timeout = Timeout(connect=None, read=None, total=None), verify = True, cert = None
proxies = OrderedDict()

def send(
self, request, stream=False, timeout=None, verify=True, cert=None, proxies=None
):
"""Sends PreparedRequest object. Returns Response object.

:param request: The :class:`PreparedRequest <PreparedRequest>` being sent.
:param stream: (optional) Whether to stream the request content.
:param timeout: (optional) How long to wait for the server to send
data before giving up, as a float, or a :ref:`(connect timeout,
read timeout) <timeouts>` tuple.
:type timeout: float or tuple or urllib3 Timeout object
:param verify: (optional) Either a boolean, in which case it controls whether
we verify the server's TLS certificate, or a string, in which case it
must be a path to a CA bundle to use
:param cert: (optional) Any user-provided SSL certificate to be trusted.
:param proxies: (optional) The proxies dictionary to apply to the request.
:rtype: requests.Response
"""

try:
conn = self._get_connection(request, verify, proxies=proxies, cert=cert)
except LocationValueError as e:
raise InvalidURL(e, request=request)

self.cert_verify(conn, request.url, verify, cert)
url = self.request_url(request, proxies)
self.add_headers(
request,
stream=stream,
timeout=timeout,
verify=verify,
cert=cert,
proxies=proxies,
)

chunked = not (request.body is None or "Content-Length" in request.headers)

if isinstance(timeout, tuple):
try:
connect, read = timeout
timeout = TimeoutSauce(connect=connect, read=read)
except ValueError:
raise ValueError(
f"Invalid timeout {timeout}. Pass a (connect, read) timeout tuple, "
f"or a single float to set both timeouts to the same value."
)
elif isinstance(timeout, TimeoutSauce):
pass
else:
timeout = TimeoutSauce(connect=timeout, read=timeout)

try:
resp = conn.urlopen(
method=request.method,
url=url,
body=request.body,
headers=request.headers,
redirect=False,
assert_same_host=False,
preload_content=False,
decode_content=False,
retries=self.max_retries,
timeout=timeout,
chunked=chunked,
)

except (ProtocolError, OSError) as err:
raise ConnectionError(err, request=request)

except MaxRetryError as e:
if isinstance(e.reason, ConnectTimeoutError):
# TODO: Remove this in 3.0.0: see #2811
if not isinstance(e.reason, NewConnectionError):
raise ConnectTimeout(e, request=request)

if isinstance(e.reason, ResponseError):
raise RetryError(e, request=request)

if isinstance(e.reason, _ProxyError):
raise ProxyError(e, request=request)

if isinstance(e.reason, _SSLError):
# This branch is for urllib3 v1.22 and later.
raise SSLError(e, request=request)

> raise ConnectionError(e, request=request)
E requests.exceptions.ConnectionError: HTTPSConnectionPool(host='addons.allizom.org', port=443): Max retries exceeded with url: /api/v5/addons/upload/ (Caused by NameResolutionError("<urllib3.connection.HTTPSConnection object at 0x103756f90>: Failed to resolve 'addons.allizom.org' ([Errno 8] nodename nor servname provided, or not known)"))

venv/lib/python3.11/site-packages/requests/adapters.py:597: ConnectionError
Failed tests/api_w/test_addon_uploads.py::test_upload_extension_with_localizations_in_xpi 0.00
self = <urllib3.connection.HTTPSConnection object at 0x1040ce7d0>

def _new_conn(self) -> socket.socket:
"""Establish a socket connection and set nodelay settings on it.

:return: New socket connection.
"""
try:
> sock = connection.create_connection(
(self._dns_host, self.port),
self.timeout,
source_address=self.source_address,
socket_options=self.socket_options,
)

venv/lib/python3.11/site-packages/urllib3/connection.py:196:
_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _
venv/lib/python3.11/site-packages/urllib3/util/connection.py:60: in create_connection
for res in socket.getaddrinfo(host, port, family, socket.SOCK_STREAM):
_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _

host = 'addons.allizom.org', port = 443, family = <AddressFamily.AF_UNSPEC: 0>, type = <SocketKind.SOCK_STREAM: 1>, proto = 0, flags = 0

def getaddrinfo(host, port, family=0, type=0, proto=0, flags=0):
"""Resolve host and port into list of address info entries.

Translate the host/port argument into a sequence of 5-tuples that contain
all the necessary arguments for creating a socket connected to that service.
host is a domain name, a string representation of an IPv4/v6 address or
None. port is a string service name such as 'http', a numeric port number or
None. By passing None as the value of host and port, you can pass NULL to
the underlying C API.

The family, type and proto arguments can be optionally specified in order to
narrow the list of addresses returned. Passing zero as a value for each of
these arguments selects the full range of results.
"""
# We override this function since we want to translate the numeric family
# and socket type values to enum constants.
addrlist = []
> for res in _socket.getaddrinfo(host, port, family, type, proto, flags):
E socket.gaierror: [Errno 8] nodename nor servname provided, or not known

/Library/Frameworks/Python.framework/Versions/3.11/lib/python3.11/socket.py:962: gaierror

The above exception was the direct cause of the following exception:

self = <urllib3.connectionpool.HTTPSConnectionPool object at 0x1040cf990>, method = 'POST', url = '/api/v5/addons/upload/'
body = b'--95552262ebd725da2dec5eae4681885a\r\nContent-Disposition: form-data; name="channel"\r\n\r\nlisted\r\n--95552262ebd7...05\x06\x00\x00\x00\x00\t\x00\t\x00\xe8\x02\x00\x00\xe9\x08\x01\x00\x00\x00\r\n--95552262ebd725da2dec5eae4681885a--\r\n'
headers = {'User-Agent': 'python-requests/2.32.0', 'Accept-Encoding': 'gzip, deflate', 'Accept': '*/*', 'Connection': 'keep-aliv...yuvakt3v', 'Content-Length': '68832', 'Content-Type': 'multipart/form-data; boundary=95552262ebd725da2dec5eae4681885a'}
retries = Retry(total=0, connect=None, read=False, redirect=None, status=None), redirect = False, assert_same_host = False, timeout = Timeout(connect=None, read=None, total=None), pool_timeout = None
release_conn = False, chunked = False, body_pos = None, preload_content = False, decode_content = False, response_kw = {}
parsed_url = Url(scheme=None, auth=None, host=None, port=None, path='/api/v5/addons/upload/', query=None, fragment=None), destination_scheme = None, conn = None, release_this_conn = True
http_tunnel_required = False, err = None, clean_exit = False

def urlopen( # type: ignore[override]
self,
method: str,
url: str,
body: _TYPE_BODY | None = None,
headers: typing.Mapping[str, str] | None = None,
retries: Retry | bool | int | None = None,
redirect: bool = True,
assert_same_host: bool = True,
timeout: _TYPE_TIMEOUT = _DEFAULT_TIMEOUT,
pool_timeout: int | None = None,
release_conn: bool | None = None,
chunked: bool = False,
body_pos: _TYPE_BODY_POSITION | None = None,
preload_content: bool = True,
decode_content: bool = True,
**response_kw: typing.Any,
) -> BaseHTTPResponse:
"""
Get a connection from the pool and perform an HTTP request. This is the
lowest level call for making a request, so you'll need to specify all
the raw details.

.. note::

More commonly, it's appropriate to use a convenience method
such as :meth:`request`.

.. note::

`release_conn` will only behave as expected if
`preload_content=False` because we want to make
`preload_content=False` the default behaviour someday soon without
breaking backwards compatibility.

:param method:
HTTP request method (such as GET, POST, PUT, etc.)

:param url:
The URL to perform the request on.

:param body:
Data to send in the request body, either :class:`str`, :class:`bytes`,
an iterable of :class:`str`/:class:`bytes`, or a file-like object.

:param headers:
Dictionary of custom headers to send, such as User-Agent,
If-None-Match, etc. If None, pool headers are used. If provided,
these headers completely replace any pool-specific headers.

:param retries:
Configure the number of retries to allow before raising a
:class:`~urllib3.exceptions.MaxRetryError` exception.

If ``None`` (default) will retry 3 times, see ``Retry.DEFAULT``. Pass a
:class:`~urllib3.util.retry.Retry` object for fine-grained control
over different types of retries.
Pass an integer number to retry connection errors that many times,
but no other types of errors. Pass zero to never retry.

If ``False``, then retries are disabled and any exception is raised
immediately. Also, instead of raising a MaxRetryError on redirects,
the redirect response will be returned.

:type retries: :class:`~urllib3.util.retry.Retry`, False, or an int.

:param redirect:
If True, automatically handle redirects (status codes 301, 302,
303, 307, 308). Each redirect counts as a retry. Disabling retries
will disable redirect, too.

:param assert_same_host:
If ``True``, will make sure that the host of the pool requests is
consistent else will raise HostChangedError. When ``False``, you can
use the pool on an HTTP proxy and request foreign hosts.

:param timeout:
If specified, overrides the default timeout for this one
request. It may be a float (in seconds) or an instance of
:class:`urllib3.util.Timeout`.

:param pool_timeout:
If set and the pool is set to block=True, then this method will
block for ``pool_timeout`` seconds and raise EmptyPoolError if no
connection is available within the time period.

:param bool preload_content:
If True, the response's body will be preloaded into memory.

:param bool decode_content:
If True, will attempt to decode the body based on the
'content-encoding' header.

:param release_conn:
If False, then the urlopen call will not release the connection
back into the pool once a response is received (but will release if
you read the entire contents of the response such as when
`preload_content=True`). This is useful if you're not preloading
the response's content immediately. You will need to call
``r.release_conn()`` on the response ``r`` to return the connection
back into the pool. If None, it takes the value of ``preload_content``
which defaults to ``True``.

:param bool chunked:
If True, urllib3 will send the body using chunked transfer
encoding. Otherwise, urllib3 will send the body using the standard
content-length form. Defaults to False.

:param int body_pos:
Position to seek to in file-like body in the event of a retry or
redirect. Typically this won't need to be set because urllib3 will
auto-populate the value when needed.
"""
parsed_url = parse_url(url)
destination_scheme = parsed_url.scheme

if headers is None:
headers = self.headers

if not isinstance(retries, Retry):
retries = Retry.from_int(retries, redirect=redirect, default=self.retries)

if release_conn is None:
release_conn = preload_content

# Check host
if assert_same_host and not self.is_same_host(url):
raise HostChangedError(self, url, retries)

# Ensure that the URL we're connecting to is properly encoded
if url.startswith("/"):
url = to_str(_encode_target(url))
else:
url = to_str(parsed_url.url)

conn = None

# Track whether `conn` needs to be released before
# returning/raising/recursing. Update this variable if necessary, and
# leave `release_conn` constant throughout the function. That way, if
# the function recurses, the original value of `release_conn` will be
# passed down into the recursive call, and its value will be respected.
#
# See issue #651 [1] for details.
#
# [1] <https://github.com/urllib3/urllib3/issues/651>
release_this_conn = release_conn

http_tunnel_required = connection_requires_http_tunnel(
self.proxy, self.proxy_config, destination_scheme
)

# Merge the proxy headers. Only done when not using HTTP CONNECT. We
# have to copy the headers dict so we can safely change it without those
# changes being reflected in anyone else's copy.
if not http_tunnel_required:
headers = headers.copy() # type: ignore[attr-defined]
headers.update(self.proxy_headers) # type: ignore[union-attr]

# Must keep the exception bound to a separate variable or else Python 3
# complains about UnboundLocalError.
err = None

# Keep track of whether we cleanly exited the except block. This
# ensures we do proper cleanup in finally.
clean_exit = False

# Rewind body position, if needed. Record current position
# for future rewinds in the event of a redirect/retry.
body_pos = set_file_position(body, body_pos)

try:
# Request a connection from the queue.
timeout_obj = self._get_timeout(timeout)
conn = self._get_conn(timeout=pool_timeout)

conn.timeout = timeout_obj.connect_timeout # type: ignore[assignment]

# Is this a closed/new connection that requires CONNECT tunnelling?
if self.proxy is not None and http_tunnel_required and conn.is_closed:
try:
self._prepare_proxy(conn)
except (BaseSSLError, OSError, SocketTimeout) as e:
self._raise_timeout(
err=e, url=self.proxy.url, timeout_value=conn.timeout
)
raise

# If we're going to release the connection in ``finally:``, then
# the response doesn't need to know about the connection. Otherwise
# it will also try to release it and we'll have a double-release
# mess.
response_conn = conn if not release_conn else None

# Make the request on the HTTPConnection object
> response = self._make_request(
conn,
method,
url,
timeout=timeout_obj,
body=body,
headers=headers,
chunked=chunked,
retries=retries,
response_conn=response_conn,
preload_content=preload_content,
decode_content=decode_content,
**response_kw,
)

venv/lib/python3.11/site-packages/urllib3/connectionpool.py:789:
_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _
venv/lib/python3.11/site-packages/urllib3/connectionpool.py:490: in _make_request
raise new_e
venv/lib/python3.11/site-packages/urllib3/connectionpool.py:466: in _make_request
self._validate_conn(conn)
venv/lib/python3.11/site-packages/urllib3/connectionpool.py:1095: in _validate_conn
conn.connect()
venv/lib/python3.11/site-packages/urllib3/connection.py:615: in connect
self.sock = sock = self._new_conn()
_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _

self = <urllib3.connection.HTTPSConnection object at 0x1040ce7d0>

def _new_conn(self) -> socket.socket:
"""Establish a socket connection and set nodelay settings on it.

:return: New socket connection.
"""
try:
sock = connection.create_connection(
(self._dns_host, self.port),
self.timeout,
source_address=self.source_address,
socket_options=self.socket_options,
)
except socket.gaierror as e:
> raise NameResolutionError(self.host, self, e) from e
E urllib3.exceptions.NameResolutionError: <urllib3.connection.HTTPSConnection object at 0x1040ce7d0>: Failed to resolve 'addons.allizom.org' ([Errno 8] nodename nor servname provided, or not known)

venv/lib/python3.11/site-packages/urllib3/connection.py:203: NameResolutionError

The above exception was the direct cause of the following exception:

self = <requests.adapters.HTTPAdapter object at 0x1040cebd0>, request = <PreparedRequest [POST]>, stream = False, timeout = Timeout(connect=None, read=None, total=None), verify = True, cert = None
proxies = OrderedDict()

def send(
self, request, stream=False, timeout=None, verify=True, cert=None, proxies=None
):
"""Sends PreparedRequest object. Returns Response object.

:param request: The :class:`PreparedRequest <PreparedRequest>` being sent.
:param stream: (optional) Whether to stream the request content.
:param timeout: (optional) How long to wait for the server to send
data before giving up, as a float, or a :ref:`(connect timeout,
read timeout) <timeouts>` tuple.
:type timeout: float or tuple or urllib3 Timeout object
:param verify: (optional) Either a boolean, in which case it controls whether
we verify the server's TLS certificate, or a string, in which case it
must be a path to a CA bundle to use
:param cert: (optional) Any user-provided SSL certificate to be trusted.
:param proxies: (optional) The proxies dictionary to apply to the request.
:rtype: requests.Response
"""

try:
conn = self._get_connection(request, verify, proxies=proxies, cert=cert)
except LocationValueError as e:
raise InvalidURL(e, request=request)

self.cert_verify(conn, request.url, verify, cert)
url = self.request_url(request, proxies)
self.add_headers(
request,
stream=stream,
timeout=timeout,
verify=verify,
cert=cert,
proxies=proxies,
)

chunked = not (request.body is None or "Content-Length" in request.headers)

if isinstance(timeout, tuple):
try:
connect, read = timeout
timeout = TimeoutSauce(connect=connect, read=read)
except ValueError:
raise ValueError(
f"Invalid timeout {timeout}. Pass a (connect, read) timeout tuple, "
f"or a single float to set both timeouts to the same value."
)
elif isinstance(timeout, TimeoutSauce):
pass
else:
timeout = TimeoutSauce(connect=timeout, read=timeout)

try:
> resp = conn.urlopen(
method=request.method,
url=url,
body=request.body,
headers=request.headers,
redirect=False,
assert_same_host=False,
preload_content=False,
decode_content=False,
retries=self.max_retries,
timeout=timeout,
chunked=chunked,
)

venv/lib/python3.11/site-packages/requests/adapters.py:564:
_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _
venv/lib/python3.11/site-packages/urllib3/connectionpool.py:843: in urlopen
retries = retries.increment(
_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _

self = Retry(total=0, connect=None, read=False, redirect=None, status=None), method = 'POST', url = '/api/v5/addons/upload/', response = None
error = NameResolutionError("<urllib3.connection.HTTPSConnection object at 0x1040ce7d0>: Failed to resolve 'addons.allizom.org' ([Errno 8] nodename nor servname provided, or not known)")
_pool = <urllib3.connectionpool.HTTPSConnectionPool object at 0x1040cf990>, _stacktrace = <traceback object at 0x1040cfc40>

def increment(
self,
method: str | None = None,
url: str | None = None,
response: BaseHTTPResponse | None = None,
error: Exception | None = None,
_pool: ConnectionPool | None = None,
_stacktrace: TracebackType | None = None,
) -> Self:
"""Return a new Retry object with incremented retry counters.

:param response: A response object, or None, if the server did not
return a response.
:type response: :class:`~urllib3.response.BaseHTTPResponse`
:param Exception error: An error encountered during the request, or
None if the response was received successfully.

:return: A new ``Retry`` object.
"""
if self.total is False and error:
# Disabled, indicate to re-raise the error.
raise reraise(type(error), error, _stacktrace)

total = self.total
if total is not None:
total -= 1

connect = self.connect
read = self.read
redirect = self.redirect
status_count = self.status
other = self.other
cause = "unknown"
status = None
redirect_location = None

if error and self._is_connection_error(error):
# Connect retry?
if connect is False:
raise reraise(type(error), error, _stacktrace)
elif connect is not None:
connect -= 1

elif error and self._is_read_error(error):
# Read retry?
if read is False or method is None or not self._is_method_retryable(method):
raise reraise(type(error), error, _stacktrace)
elif read is not None:
read -= 1

elif error:
# Other retry?
if other is not None:
other -= 1

elif response and response.get_redirect_location():
# Redirect retry?
if redirect is not None:
redirect -= 1
cause = "too many redirects"
response_redirect_location = response.get_redirect_location()
if response_redirect_location:
redirect_location = response_redirect_location
status = response.status

else:
# Incrementing because of a server error like a 500 in
# status_forcelist and the given method is in the allowed_methods
cause = ResponseError.GENERIC_ERROR
if response and response.status:
if status_count is not None:
status_count -= 1
cause = ResponseError.SPECIFIC_ERROR.format(status_code=response.status)
status = response.status

history = self.history + (
RequestHistory(method, url, error, status, redirect_location),
)

new_retry = self.new(
total=total,
connect=connect,
read=read,
redirect=redirect,
status=status_count,
other=other,
history=history,
)

if new_retry.is_exhausted():
reason = error or ResponseError(cause)
> raise MaxRetryError(_pool, url, reason) from reason # type: ignore[arg-type]
E urllib3.exceptions.MaxRetryError: HTTPSConnectionPool(host='addons.allizom.org', port=443): Max retries exceeded with url: /api/v5/addons/upload/ (Caused by NameResolutionError("<urllib3.connection.HTTPSConnection object at 0x1040ce7d0>: Failed to resolve 'addons.allizom.org' ([Errno 8] nodename nor servname provided, or not known)"))

venv/lib/python3.11/site-packages/urllib3/util/retry.py:519: MaxRetryError

During handling of the above exception, another exception occurred:

base_url = 'https://addons.allizom.org', session_auth = 'ldvd5ag27bkfpukx6rn2lcj0yuvakt3v'
variables = {'4mb_addon_slug': '4mb_addon_slug', 'addon_detail_guid': '{446900e4-71c2-419f-a6a7-df9c091e268b}', 'addon_detail_id':...dd-ons must comply with Mozilla’s Add-on Policies and are subject to manual review at any time after submission.', ...}

@pytest.mark.serial
@pytest.mark.create_session("api_user")
def test_upload_extension_with_localizations_in_xpi(base_url, session_auth, variables):
"""Addon translations set in a 'locales' file in the .xpi should be reflected
in the API response returned after the addon is successfully created"""
with open("sample-addons/localizations.xpi", "rb") as file:
> upload = requests.post(
url=f"{base_url}{_upload}",
headers={"Authorization": f"Session {session_auth}"},
files={"upload": file},
data={"channel": "listed"},
)

tests/api_w/test_addon_uploads.py:869:
_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _
venv/lib/python3.11/site-packages/requests/api.py:115: in post
return request("post", url, data=data, json=json, **kwargs)
venv/lib/python3.11/site-packages/requests/api.py:59: in request
return session.request(method=method, url=url, **kwargs)
venv/lib/python3.11/site-packages/requests/sessions.py:589: in request
resp = self.send(prep, **send_kwargs)
venv/lib/python3.11/site-packages/requests/sessions.py:703: in send
r = adapter.send(request, **kwargs)
_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _

self = <requests.adapters.HTTPAdapter object at 0x1040cebd0>, request = <PreparedRequest [POST]>, stream = False, timeout = Timeout(connect=None, read=None, total=None), verify = True, cert = None
proxies = OrderedDict()

def send(
self, request, stream=False, timeout=None, verify=True, cert=None, proxies=None
):
"""Sends PreparedRequest object. Returns Response object.

:param request: The :class:`PreparedRequest <PreparedRequest>` being sent.
:param stream: (optional) Whether to stream the request content.
:param timeout: (optional) How long to wait for the server to send
data before giving up, as a float, or a :ref:`(connect timeout,
read timeout) <timeouts>` tuple.
:type timeout: float or tuple or urllib3 Timeout object
:param verify: (optional) Either a boolean, in which case it controls whether
we verify the server's TLS certificate, or a string, in which case it
must be a path to a CA bundle to use
:param cert: (optional) Any user-provided SSL certificate to be trusted.
:param proxies: (optional) The proxies dictionary to apply to the request.
:rtype: requests.Response
"""

try:
conn = self._get_connection(request, verify, proxies=proxies, cert=cert)
except LocationValueError as e:
raise InvalidURL(e, request=request)

self.cert_verify(conn, request.url, verify, cert)
url = self.request_url(request, proxies)
self.add_headers(
request,
stream=stream,
timeout=timeout,
verify=verify,
cert=cert,
proxies=proxies,
)

chunked = not (request.body is None or "Content-Length" in request.headers)

if isinstance(timeout, tuple):
try:
connect, read = timeout
timeout = TimeoutSauce(connect=connect, read=read)
except ValueError:
raise ValueError(
f"Invalid timeout {timeout}. Pass a (connect, read) timeout tuple, "
f"or a single float to set both timeouts to the same value."
)
elif isinstance(timeout, TimeoutSauce):
pass
else:
timeout = TimeoutSauce(connect=timeout, read=timeout)

try:
resp = conn.urlopen(
method=request.method,
url=url,
body=request.body,
headers=request.headers,
redirect=False,
assert_same_host=False,
preload_content=False,
decode_content=False,
retries=self.max_retries,
timeout=timeout,
chunked=chunked,
)

except (ProtocolError, OSError) as err:
raise ConnectionError(err, request=request)

except MaxRetryError as e:
if isinstance(e.reason, ConnectTimeoutError):
# TODO: Remove this in 3.0.0: see #2811
if not isinstance(e.reason, NewConnectionError):
raise ConnectTimeout(e, request=request)

if isinstance(e.reason, ResponseError):
raise RetryError(e, request=request)

if isinstance(e.reason, _ProxyError):
raise ProxyError(e, request=request)

if isinstance(e.reason, _SSLError):
# This branch is for urllib3 v1.22 and later.
raise SSLError(e, request=request)

> raise ConnectionError(e, request=request)
E requests.exceptions.ConnectionError: HTTPSConnectionPool(host='addons.allizom.org', port=443): Max retries exceeded with url: /api/v5/addons/upload/ (Caused by NameResolutionError("<urllib3.connection.HTTPSConnection object at 0x1040ce7d0>: Failed to resolve 'addons.allizom.org' ([Errno 8] nodename nor servname provided, or not known)"))

venv/lib/python3.11/site-packages/requests/adapters.py:597: ConnectionError
Failed tests/api_w/test_addon_uploads.py::test_upload_localized_extension_json_overwrite 0.00
self = <urllib3.connection.HTTPSConnection object at 0x104121c90>

def _new_conn(self) -> socket.socket:
"""Establish a socket connection and set nodelay settings on it.

:return: New socket connection.
"""
try:
> sock = connection.create_connection(
(self._dns_host, self.port),
self.timeout,
source_address=self.source_address,
socket_options=self.socket_options,
)

venv/lib/python3.11/site-packages/urllib3/connection.py:196:
_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _
venv/lib/python3.11/site-packages/urllib3/util/connection.py:60: in create_connection
for res in socket.getaddrinfo(host, port, family, socket.SOCK_STREAM):
_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _

host = 'addons.allizom.org', port = 443, family = <AddressFamily.AF_UNSPEC: 0>, type = <SocketKind.SOCK_STREAM: 1>, proto = 0, flags = 0

def getaddrinfo(host, port, family=0, type=0, proto=0, flags=0):
"""Resolve host and port into list of address info entries.

Translate the host/port argument into a sequence of 5-tuples that contain
all the necessary arguments for creating a socket connected to that service.
host is a domain name, a string representation of an IPv4/v6 address or
None. port is a string service name such as 'http', a numeric port number or
None. By passing None as the value of host and port, you can pass NULL to
the underlying C API.

The family, type and proto arguments can be optionally specified in order to
narrow the list of addresses returned. Passing zero as a value for each of
these arguments selects the full range of results.
"""
# We override this function since we want to translate the numeric family
# and socket type values to enum constants.
addrlist = []
> for res in _socket.getaddrinfo(host, port, family, type, proto, flags):
E socket.gaierror: [Errno 8] nodename nor servname provided, or not known

/Library/Frameworks/Python.framework/Versions/3.11/lib/python3.11/socket.py:962: gaierror

The above exception was the direct cause of the following exception:

self = <urllib3.connectionpool.HTTPSConnectionPool object at 0x103c11310>, method = 'POST', url = '/api/v5/addons/upload/'
body = b'--1e7848b459b89c12fb800a5bf4333706\r\nContent-Disposition: form-data; name="channel"\r\n\r\nlisted\r\n--1e7848b459b8...05\x06\x00\x00\x00\x00\t\x00\t\x00\xe8\x02\x00\x00\xe9\x08\x01\x00\x00\x00\r\n--1e7848b459b89c12fb800a5bf4333706--\r\n'
headers = {'User-Agent': 'python-requests/2.32.0', 'Accept-Encoding': 'gzip, deflate', 'Accept': '*/*', 'Connection': 'keep-aliv...yuvakt3v', 'Content-Length': '68832', 'Content-Type': 'multipart/form-data; boundary=1e7848b459b89c12fb800a5bf4333706'}
retries = Retry(total=0, connect=None, read=False, redirect=None, status=None), redirect = False, assert_same_host = False, timeout = Timeout(connect=None, read=None, total=None), pool_timeout = None
release_conn = False, chunked = False, body_pos = None, preload_content = False, decode_content = False, response_kw = {}
parsed_url = Url(scheme=None, auth=None, host=None, port=None, path='/api/v5/addons/upload/', query=None, fragment=None), destination_scheme = None, conn = None, release_this_conn = True
http_tunnel_required = False, err = None, clean_exit = False

def urlopen( # type: ignore[override]
self,
method: str,
url: str,
body: _TYPE_BODY | None = None,
headers: typing.Mapping[str, str] | None = None,
retries: Retry | bool | int | None = None,
redirect: bool = True,
assert_same_host: bool = True,
timeout: _TYPE_TIMEOUT = _DEFAULT_TIMEOUT,
pool_timeout: int | None = None,
release_conn: bool | None = None,
chunked: bool = False,
body_pos: _TYPE_BODY_POSITION | None = None,
preload_content: bool = True,
decode_content: bool = True,
**response_kw: typing.Any,
) -> BaseHTTPResponse:
"""
Get a connection from the pool and perform an HTTP request. This is the
lowest level call for making a request, so you'll need to specify all
the raw details.

.. note::

More commonly, it's appropriate to use a convenience method
such as :meth:`request`.

.. note::

`release_conn` will only behave as expected if
`preload_content=False` because we want to make
`preload_content=False` the default behaviour someday soon without
breaking backwards compatibility.

:param method:
HTTP request method (such as GET, POST, PUT, etc.)

:param url:
The URL to perform the request on.

:param body:
Data to send in the request body, either :class:`str`, :class:`bytes`,
an iterable of :class:`str`/:class:`bytes`, or a file-like object.

:param headers:
Dictionary of custom headers to send, such as User-Agent,
If-None-Match, etc. If None, pool headers are used. If provided,
these headers completely replace any pool-specific headers.

:param retries:
Configure the number of retries to allow before raising a
:class:`~urllib3.exceptions.MaxRetryError` exception.

If ``None`` (default) will retry 3 times, see ``Retry.DEFAULT``. Pass a
:class:`~urllib3.util.retry.Retry` object for fine-grained control
over different types of retries.
Pass an integer number to retry connection errors that many times,
but no other types of errors. Pass zero to never retry.

If ``False``, then retries are disabled and any exception is raised
immediately. Also, instead of raising a MaxRetryError on redirects,
the redirect response will be returned.

:type retries: :class:`~urllib3.util.retry.Retry`, False, or an int.

:param redirect:
If True, automatically handle redirects (status codes 301, 302,
303, 307, 308). Each redirect counts as a retry. Disabling retries
will disable redirect, too.

:param assert_same_host:
If ``True``, will make sure that the host of the pool requests is
consistent else will raise HostChangedError. When ``False``, you can
use the pool on an HTTP proxy and request foreign hosts.

:param timeout:
If specified, overrides the default timeout for this one
request. It may be a float (in seconds) or an instance of
:class:`urllib3.util.Timeout`.

:param pool_timeout:
If set and the pool is set to block=True, then this method will
block for ``pool_timeout`` seconds and raise EmptyPoolError if no
connection is available within the time period.

:param bool preload_content:
If True, the response's body will be preloaded into memory.

:param bool decode_content:
If True, will attempt to decode the body based on the
'content-encoding' header.

:param release_conn:
If False, then the urlopen call will not release the connection
back into the pool once a response is received (but will release if
you read the entire contents of the response such as when
`preload_content=True`). This is useful if you're not preloading
the response's content immediately. You will need to call
``r.release_conn()`` on the response ``r`` to return the connection
back into the pool. If None, it takes the value of ``preload_content``
which defaults to ``True``.

:param bool chunked:
If True, urllib3 will send the body using chunked transfer
encoding. Otherwise, urllib3 will send the body using the standard
content-length form. Defaults to False.

:param int body_pos:
Position to seek to in file-like body in the event of a retry or
redirect. Typically this won't need to be set because urllib3 will
auto-populate the value when needed.
"""
parsed_url = parse_url(url)
destination_scheme = parsed_url.scheme

if headers is None:
headers = self.headers

if not isinstance(retries, Retry):
retries = Retry.from_int(retries, redirect=redirect, default=self.retries)

if release_conn is None:
release_conn = preload_content

# Check host
if assert_same_host and not self.is_same_host(url):
raise HostChangedError(self, url, retries)

# Ensure that the URL we're connecting to is properly encoded
if url.startswith("/"):
url = to_str(_encode_target(url))
else:
url = to_str(parsed_url.url)

conn = None

# Track whether `conn` needs to be released before
# returning/raising/recursing. Update this variable if necessary, and
# leave `release_conn` constant throughout the function. That way, if
# the function recurses, the original value of `release_conn` will be
# passed down into the recursive call, and its value will be respected.
#
# See issue #651 [1] for details.
#
# [1] <https://github.com/urllib3/urllib3/issues/651>
release_this_conn = release_conn

http_tunnel_required = connection_requires_http_tunnel(
self.proxy, self.proxy_config, destination_scheme
)

# Merge the proxy headers. Only done when not using HTTP CONNECT. We
# have to copy the headers dict so we can safely change it without those
# changes being reflected in anyone else's copy.
if not http_tunnel_required:
headers = headers.copy() # type: ignore[attr-defined]
headers.update(self.proxy_headers) # type: ignore[union-attr]

# Must keep the exception bound to a separate variable or else Python 3
# complains about UnboundLocalError.
err = None

# Keep track of whether we cleanly exited the except block. This
# ensures we do proper cleanup in finally.
clean_exit = False

# Rewind body position, if needed. Record current position
# for future rewinds in the event of a redirect/retry.
body_pos = set_file_position(body, body_pos)

try:
# Request a connection from the queue.
timeout_obj = self._get_timeout(timeout)
conn = self._get_conn(timeout=pool_timeout)

conn.timeout = timeout_obj.connect_timeout # type: ignore[assignment]

# Is this a closed/new connection that requires CONNECT tunnelling?
if self.proxy is not None and http_tunnel_required and conn.is_closed:
try:
self._prepare_proxy(conn)
except (BaseSSLError, OSError, SocketTimeout) as e:
self._raise_timeout(
err=e, url=self.proxy.url, timeout_value=conn.timeout
)
raise

# If we're going to release the connection in ``finally:``, then
# the response doesn't need to know about the connection. Otherwise
# it will also try to release it and we'll have a double-release
# mess.
response_conn = conn if not release_conn else None

# Make the request on the HTTPConnection object
> response = self._make_request(
conn,
method,
url,
timeout=timeout_obj,
body=body,
headers=headers,
chunked=chunked,
retries=retries,
response_conn=response_conn,
preload_content=preload_content,
decode_content=decode_content,
**response_kw,
)

venv/lib/python3.11/site-packages/urllib3/connectionpool.py:789:
_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _
venv/lib/python3.11/site-packages/urllib3/connectionpool.py:490: in _make_request
raise new_e
venv/lib/python3.11/site-packages/urllib3/connectionpool.py:466: in _make_request
self._validate_conn(conn)
venv/lib/python3.11/site-packages/urllib3/connectionpool.py:1095: in _validate_conn
conn.connect()
venv/lib/python3.11/site-packages/urllib3/connection.py:615: in connect
self.sock = sock = self._new_conn()
_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _

self = <urllib3.connection.HTTPSConnection object at 0x104121c90>

def _new_conn(self) -> socket.socket:
"""Establish a socket connection and set nodelay settings on it.

:return: New socket connection.
"""
try:
sock = connection.create_connection(
(self._dns_host, self.port),
self.timeout,
source_address=self.source_address,
socket_options=self.socket_options,
)
except socket.gaierror as e:
> raise NameResolutionError(self.host, self, e) from e
E urllib3.exceptions.NameResolutionError: <urllib3.connection.HTTPSConnection object at 0x104121c90>: Failed to resolve 'addons.allizom.org' ([Errno 8] nodename nor servname provided, or not known)

venv/lib/python3.11/site-packages/urllib3/connection.py:203: NameResolutionError

The above exception was the direct cause of the following exception:

self = <requests.adapters.HTTPAdapter object at 0x103c10350>, request = <PreparedRequest [POST]>, stream = False, timeout = Timeout(connect=None, read=None, total=None), verify = True, cert = None
proxies = OrderedDict()

def send(
self, request, stream=False, timeout=None, verify=True, cert=None, proxies=None
):
"""Sends PreparedRequest object. Returns Response object.

:param request: The :class:`PreparedRequest <PreparedRequest>` being sent.
:param stream: (optional) Whether to stream the request content.
:param timeout: (optional) How long to wait for the server to send
data before giving up, as a float, or a :ref:`(connect timeout,
read timeout) <timeouts>` tuple.
:type timeout: float or tuple or urllib3 Timeout object
:param verify: (optional) Either a boolean, in which case it controls whether
we verify the server's TLS certificate, or a string, in which case it
must be a path to a CA bundle to use
:param cert: (optional) Any user-provided SSL certificate to be trusted.
:param proxies: (optional) The proxies dictionary to apply to the request.
:rtype: requests.Response
"""

try:
conn = self._get_connection(request, verify, proxies=proxies, cert=cert)
except LocationValueError as e:
raise InvalidURL(e, request=request)

self.cert_verify(conn, request.url, verify, cert)
url = self.request_url(request, proxies)
self.add_headers(
request,
stream=stream,
timeout=timeout,
verify=verify,
cert=cert,
proxies=proxies,
)

chunked = not (request.body is None or "Content-Length" in request.headers)

if isinstance(timeout, tuple):
try:
connect, read = timeout
timeout = TimeoutSauce(connect=connect, read=read)
except ValueError:
raise ValueError(
f"Invalid timeout {timeout}. Pass a (connect, read) timeout tuple, "
f"or a single float to set both timeouts to the same value."
)
elif isinstance(timeout, TimeoutSauce):
pass
else:
timeout = TimeoutSauce(connect=timeout, read=timeout)

try:
> resp = conn.urlopen(
method=request.method,
url=url,
body=request.body,
headers=request.headers,
redirect=False,
assert_same_host=False,
preload_content=False,
decode_content=False,
retries=self.max_retries,
timeout=timeout,
chunked=chunked,
)

venv/lib/python3.11/site-packages/requests/adapters.py:564:
_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _
venv/lib/python3.11/site-packages/urllib3/connectionpool.py:843: in urlopen
retries = retries.increment(
_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _

self = Retry(total=0, connect=None, read=False, redirect=None, status=None), method = 'POST', url = '/api/v5/addons/upload/', response = None
error = NameResolutionError("<urllib3.connection.HTTPSConnection object at 0x104121c90>: Failed to resolve 'addons.allizom.org' ([Errno 8] nodename nor servname provided, or not known)")
_pool = <urllib3.connectionpool.HTTPSConnectionPool object at 0x103c11310>, _stacktrace = <traceback object at 0x104122840>

def increment(
self,
method: str | None = None,
url: str | None = None,
response: BaseHTTPResponse | None = None,
error: Exception | None = None,
_pool: ConnectionPool | None = None,
_stacktrace: TracebackType | None = None,
) -> Self:
"""Return a new Retry object with incremented retry counters.

:param response: A response object, or None, if the server did not
return a response.
:type response: :class:`~urllib3.response.BaseHTTPResponse`
:param Exception error: An error encountered during the request, or
None if the response was received successfully.

:return: A new ``Retry`` object.
"""
if self.total is False and error:
# Disabled, indicate to re-raise the error.
raise reraise(type(error), error, _stacktrace)

total = self.total
if total is not None:
total -= 1

connect = self.connect
read = self.read
redirect = self.redirect
status_count = self.status
other = self.other
cause = "unknown"
status = None
redirect_location = None

if error and self._is_connection_error(error):
# Connect retry?
if connect is False:
raise reraise(type(error), error, _stacktrace)
elif connect is not None:
connect -= 1

elif error and self._is_read_error(error):
# Read retry?
if read is False or method is None or not self._is_method_retryable(method):
raise reraise(type(error), error, _stacktrace)
elif read is not None:
read -= 1

elif error:
# Other retry?
if other is not None:
other -= 1

elif response and response.get_redirect_location():
# Redirect retry?
if redirect is not None:
redirect -= 1
cause = "too many redirects"
response_redirect_location = response.get_redirect_location()
if response_redirect_location:
redirect_location = response_redirect_location
status = response.status

else:
# Incrementing because of a server error like a 500 in
# status_forcelist and the given method is in the allowed_methods
cause = ResponseError.GENERIC_ERROR
if response and response.status:
if status_count is not None:
status_count -= 1
cause = ResponseError.SPECIFIC_ERROR.format(status_code=response.status)
status = response.status

history = self.history + (
RequestHistory(method, url, error, status, redirect_location),
)

new_retry = self.new(
total=total,
connect=connect,
read=read,
redirect=redirect,
status=status_count,
other=other,
history=history,
)

if new_retry.is_exhausted():
reason = error or ResponseError(cause)
> raise MaxRetryError(_pool, url, reason) from reason # type: ignore[arg-type]
E urllib3.exceptions.MaxRetryError: HTTPSConnectionPool(host='addons.allizom.org', port=443): Max retries exceeded with url: /api/v5/addons/upload/ (Caused by NameResolutionError("<urllib3.connection.HTTPSConnection object at 0x104121c90>: Failed to resolve 'addons.allizom.org' ([Errno 8] nodename nor servname provided, or not known)"))

venv/lib/python3.11/site-packages/urllib3/util/retry.py:519: MaxRetryError

During handling of the above exception, another exception occurred:

base_url = 'https://addons.allizom.org', session_auth = 'ldvd5ag27bkfpukx6rn2lcj0yuvakt3v'

@pytest.mark.serial
@pytest.mark.create_session("api_user")
def test_upload_localized_extension_json_overwrite(base_url, session_auth):
"""If an addon with a 'locales' file defined in the .xpi sets different translations
in the request JSON object, the JSON values should override the locales file from the .xpi
"""
with open("sample-addons/localizations.xpi", "rb") as file:
> upload = requests.post(
url=f"{base_url}{_upload}",
headers={"Authorization": f"Session {session_auth}"},
files={"upload": file},
data={"channel": "listed"},
)

tests/api_w/test_addon_uploads.py:907:
_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _
venv/lib/python3.11/site-packages/requests/api.py:115: in post
return request("post", url, data=data, json=json, **kwargs)
venv/lib/python3.11/site-packages/requests/api.py:59: in request
return session.request(method=method, url=url, **kwargs)
venv/lib/python3.11/site-packages/requests/sessions.py:589: in request
resp = self.send(prep, **send_kwargs)
venv/lib/python3.11/site-packages/requests/sessions.py:703: in send
r = adapter.send(request, **kwargs)
_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _

self = <requests.adapters.HTTPAdapter object at 0x103c10350>, request = <PreparedRequest [POST]>, stream = False, timeout = Timeout(connect=None, read=None, total=None), verify = True, cert = None
proxies = OrderedDict()

def send(
self, request, stream=False, timeout=None, verify=True, cert=None, proxies=None
):
"""Sends PreparedRequest object. Returns Response object.

:param request: The :class:`PreparedRequest <PreparedRequest>` being sent.
:param stream: (optional) Whether to stream the request content.
:param timeout: (optional) How long to wait for the server to send
data before giving up, as a float, or a :ref:`(connect timeout,
read timeout) <timeouts>` tuple.
:type timeout: float or tuple or urllib3 Timeout object
:param verify: (optional) Either a boolean, in which case it controls whether
we verify the server's TLS certificate, or a string, in which case it
must be a path to a CA bundle to use
:param cert: (optional) Any user-provided SSL certificate to be trusted.
:param proxies: (optional) The proxies dictionary to apply to the request.
:rtype: requests.Response
"""

try:
conn = self._get_connection(request, verify, proxies=proxies, cert=cert)
except LocationValueError as e:
raise InvalidURL(e, request=request)

self.cert_verify(conn, request.url, verify, cert)
url = self.request_url(request, proxies)
self.add_headers(
request,
stream=stream,
timeout=timeout,
verify=verify,
cert=cert,
proxies=proxies,
)

chunked = not (request.body is None or "Content-Length" in request.headers)

if isinstance(timeout, tuple):
try:
connect, read = timeout
timeout = TimeoutSauce(connect=connect, read=read)
except ValueError:
raise ValueError(
f"Invalid timeout {timeout}. Pass a (connect, read) timeout tuple, "
f"or a single float to set both timeouts to the same value."
)
elif isinstance(timeout, TimeoutSauce):
pass
else:
timeout = TimeoutSauce(connect=timeout, read=timeout)

try:
resp = conn.urlopen(
method=request.method,
url=url,
body=request.body,
headers=request.headers,
redirect=False,
assert_same_host=False,
preload_content=False,
decode_content=False,
retries=self.max_retries,
timeout=timeout,
chunked=chunked,
)

except (ProtocolError, OSError) as err:
raise ConnectionError(err, request=request)

except MaxRetryError as e:
if isinstance(e.reason, ConnectTimeoutError):
# TODO: Remove this in 3.0.0: see #2811
if not isinstance(e.reason, NewConnectionError):
raise ConnectTimeout(e, request=request)

if isinstance(e.reason, ResponseError):
raise RetryError(e, request=request)

if isinstance(e.reason, _ProxyError):
raise ProxyError(e, request=request)

if isinstance(e.reason, _SSLError):
# This branch is for urllib3 v1.22 and later.
raise SSLError(e, request=request)

> raise ConnectionError(e, request=request)
E requests.exceptions.ConnectionError: HTTPSConnectionPool(host='addons.allizom.org', port=443): Max retries exceeded with url: /api/v5/addons/upload/ (Caused by NameResolutionError("<urllib3.connection.HTTPSConnection object at 0x104121c90>: Failed to resolve 'addons.allizom.org' ([Errno 8] nodename nor servname provided, or not known)"))

venv/lib/python3.11/site-packages/requests/adapters.py:597: ConnectionError
Failed tests/api_w/test_addon_uploads.py::test_upload_addon_with_guid_from_deleted_addon 0.00
self = <urllib3.connection.HTTPSConnection object at 0x103713110>

def _new_conn(self) -> socket.socket:
"""Establish a socket connection and set nodelay settings on it.

:return: New socket connection.
"""
try:
> sock = connection.create_connection(
(self._dns_host, self.port),
self.timeout,
source_address=self.source_address,
socket_options=self.socket_options,
)

venv/lib/python3.11/site-packages/urllib3/connection.py:196:
_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _
venv/lib/python3.11/site-packages/urllib3/util/connection.py:60: in create_connection
for res in socket.getaddrinfo(host, port, family, socket.SOCK_STREAM):
_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _

host = 'addons.allizom.org', port = 443, family = <AddressFamily.AF_UNSPEC: 0>, type = <SocketKind.SOCK_STREAM: 1>, proto = 0, flags = 0

def getaddrinfo(host, port, family=0, type=0, proto=0, flags=0):
"""Resolve host and port into list of address info entries.

Translate the host/port argument into a sequence of 5-tuples that contain
all the necessary arguments for creating a socket connected to that service.
host is a domain name, a string representation of an IPv4/v6 address or
None. port is a string service name such as 'http', a numeric port number or
None. By passing None as the value of host and port, you can pass NULL to
the underlying C API.

The family, type and proto arguments can be optionally specified in order to
narrow the list of addresses returned. Passing zero as a value for each of
these arguments selects the full range of results.
"""
# We override this function since we want to translate the numeric family
# and socket type values to enum constants.
addrlist = []
> for res in _socket.getaddrinfo(host, port, family, type, proto, flags):
E socket.gaierror: [Errno 8] nodename nor servname provided, or not known

/Library/Frameworks/Python.framework/Versions/3.11/lib/python3.11/socket.py:962: gaierror

The above exception was the direct cause of the following exception:

self = <urllib3.connectionpool.HTTPSConnectionPool object at 0x1037107d0>, method = 'POST', url = '/api/v5/addons/upload/'
body = b'--bcf01258cfea535c3c9419029012e14e\r\nContent-Disposition: form-data; name="channel"\r\n\r\nunlisted\r\n--bcf01258cf...5\x06\x00\x00\x00\x00\x01\x00\x01\x00;\x00\x00\x00\xc1\x00\x00\x00\x00\x00\r\n--bcf01258cfea535c3c9419029012e14e--\r\n'
headers = {'User-Agent': 'python-requests/2.32.0', 'Accept-Encoding': 'gzip, deflate', 'Accept': '*/*', 'Connection': 'keep-aliv...j0yuvakt3v', 'Content-Length': '522', 'Content-Type': 'multipart/form-data; boundary=bcf01258cfea535c3c9419029012e14e'}
retries = Retry(total=0, connect=None, read=False, redirect=None, status=None), redirect = False, assert_same_host = False, timeout = Timeout(connect=None, read=None, total=None), pool_timeout = None
release_conn = False, chunked = False, body_pos = None, preload_content = False, decode_content = False, response_kw = {}
parsed_url = Url(scheme=None, auth=None, host=None, port=None, path='/api/v5/addons/upload/', query=None, fragment=None), destination_scheme = None, conn = None, release_this_conn = True
http_tunnel_required = False, err = None, clean_exit = False

def urlopen( # type: ignore[override]
self,
method: str,
url: str,
body: _TYPE_BODY | None = None,
headers: typing.Mapping[str, str] | None = None,
retries: Retry | bool | int | None = None,
redirect: bool = True,
assert_same_host: bool = True,
timeout: _TYPE_TIMEOUT = _DEFAULT_TIMEOUT,
pool_timeout: int | None = None,
release_conn: bool | None = None,
chunked: bool = False,
body_pos: _TYPE_BODY_POSITION | None = None,
preload_content: bool = True,
decode_content: bool = True,
**response_kw: typing.Any,
) -> BaseHTTPResponse:
"""
Get a connection from the pool and perform an HTTP request. This is the
lowest level call for making a request, so you'll need to specify all
the raw details.

.. note::

More commonly, it's appropriate to use a convenience method
such as :meth:`request`.

.. note::

`release_conn` will only behave as expected if
`preload_content=False` because we want to make
`preload_content=False` the default behaviour someday soon without
breaking backwards compatibility.

:param method:
HTTP request method (such as GET, POST, PUT, etc.)

:param url:
The URL to perform the request on.

:param body:
Data to send in the request body, either :class:`str`, :class:`bytes`,
an iterable of :class:`str`/:class:`bytes`, or a file-like object.

:param headers:
Dictionary of custom headers to send, such as User-Agent,
If-None-Match, etc. If None, pool headers are used. If provided,
these headers completely replace any pool-specific headers.

:param retries:
Configure the number of retries to allow before raising a
:class:`~urllib3.exceptions.MaxRetryError` exception.

If ``None`` (default) will retry 3 times, see ``Retry.DEFAULT``. Pass a
:class:`~urllib3.util.retry.Retry` object for fine-grained control
over different types of retries.
Pass an integer number to retry connection errors that many times,
but no other types of errors. Pass zero to never retry.

If ``False``, then retries are disabled and any exception is raised
immediately. Also, instead of raising a MaxRetryError on redirects,
the redirect response will be returned.

:type retries: :class:`~urllib3.util.retry.Retry`, False, or an int.

:param redirect:
If True, automatically handle redirects (status codes 301, 302,
303, 307, 308). Each redirect counts as a retry. Disabling retries
will disable redirect, too.

:param assert_same_host:
If ``True``, will make sure that the host of the pool requests is
consistent else will raise HostChangedError. When ``False``, you can
use the pool on an HTTP proxy and request foreign hosts.

:param timeout:
If specified, overrides the default timeout for this one
request. It may be a float (in seconds) or an instance of
:class:`urllib3.util.Timeout`.

:param pool_timeout:
If set and the pool is set to block=True, then this method will
block for ``pool_timeout`` seconds and raise EmptyPoolError if no
connection is available within the time period.

:param bool preload_content:
If True, the response's body will be preloaded into memory.

:param bool decode_content:
If True, will attempt to decode the body based on the
'content-encoding' header.

:param release_conn:
If False, then the urlopen call will not release the connection
back into the pool once a response is received (but will release if
you read the entire contents of the response such as when
`preload_content=True`). This is useful if you're not preloading
the response's content immediately. You will need to call
``r.release_conn()`` on the response ``r`` to return the connection
back into the pool. If None, it takes the value of ``preload_content``
which defaults to ``True``.

:param bool chunked:
If True, urllib3 will send the body using chunked transfer
encoding. Otherwise, urllib3 will send the body using the standard
content-length form. Defaults to False.

:param int body_pos:
Position to seek to in file-like body in the event of a retry or
redirect. Typically this won't need to be set because urllib3 will
auto-populate the value when needed.
"""
parsed_url = parse_url(url)
destination_scheme = parsed_url.scheme

if headers is None:
headers = self.headers

if not isinstance(retries, Retry):
retries = Retry.from_int(retries, redirect=redirect, default=self.retries)

if release_conn is None:
release_conn = preload_content

# Check host
if assert_same_host and not self.is_same_host(url):
raise HostChangedError(self, url, retries)

# Ensure that the URL we're connecting to is properly encoded
if url.startswith("/"):
url = to_str(_encode_target(url))
else:
url = to_str(parsed_url.url)

conn = None

# Track whether `conn` needs to be released before
# returning/raising/recursing. Update this variable if necessary, and
# leave `release_conn` constant throughout the function. That way, if
# the function recurses, the original value of `release_conn` will be
# passed down into the recursive call, and its value will be respected.
#
# See issue #651 [1] for details.
#
# [1] <https://github.com/urllib3/urllib3/issues/651>
release_this_conn = release_conn

http_tunnel_required = connection_requires_http_tunnel(
self.proxy, self.proxy_config, destination_scheme
)

# Merge the proxy headers. Only done when not using HTTP CONNECT. We
# have to copy the headers dict so we can safely change it without those
# changes being reflected in anyone else's copy.
if not http_tunnel_required:
headers = headers.copy() # type: ignore[attr-defined]
headers.update(self.proxy_headers) # type: ignore[union-attr]

# Must keep the exception bound to a separate variable or else Python 3
# complains about UnboundLocalError.
err = None

# Keep track of whether we cleanly exited the except block. This
# ensures we do proper cleanup in finally.
clean_exit = False

# Rewind body position, if needed. Record current position
# for future rewinds in the event of a redirect/retry.
body_pos = set_file_position(body, body_pos)

try:
# Request a connection from the queue.
timeout_obj = self._get_timeout(timeout)
conn = self._get_conn(timeout=pool_timeout)

conn.timeout = timeout_obj.connect_timeout # type: ignore[assignment]

# Is this a closed/new connection that requires CONNECT tunnelling?
if self.proxy is not None and http_tunnel_required and conn.is_closed:
try:
self._prepare_proxy(conn)
except (BaseSSLError, OSError, SocketTimeout) as e:
self._raise_timeout(
err=e, url=self.proxy.url, timeout_value=conn.timeout
)
raise

# If we're going to release the connection in ``finally:``, then
# the response doesn't need to know about the connection. Otherwise
# it will also try to release it and we'll have a double-release
# mess.
response_conn = conn if not release_conn else None

# Make the request on the HTTPConnection object
> response = self._make_request(
conn,
method,
url,
timeout=timeout_obj,
body=body,
headers=headers,
chunked=chunked,
retries=retries,
response_conn=response_conn,
preload_content=preload_content,
decode_content=decode_content,
**response_kw,
)

venv/lib/python3.11/site-packages/urllib3/connectionpool.py:789:
_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _
venv/lib/python3.11/site-packages/urllib3/connectionpool.py:490: in _make_request
raise new_e
venv/lib/python3.11/site-packages/urllib3/connectionpool.py:466: in _make_request
self._validate_conn(conn)
venv/lib/python3.11/site-packages/urllib3/connectionpool.py:1095: in _validate_conn
conn.connect()
venv/lib/python3.11/site-packages/urllib3/connection.py:615: in connect
self.sock = sock = self._new_conn()
_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _

self = <urllib3.connection.HTTPSConnection object at 0x103713110>

def _new_conn(self) -> socket.socket:
"""Establish a socket connection and set nodelay settings on it.

:return: New socket connection.
"""
try:
sock = connection.create_connection(
(self._dns_host, self.port),
self.timeout,
source_address=self.source_address,
socket_options=self.socket_options,
)
except socket.gaierror as e:
> raise NameResolutionError(self.host, self, e) from e
E urllib3.exceptions.NameResolutionError: <urllib3.connection.HTTPSConnection object at 0x103713110>: Failed to resolve 'addons.allizom.org' ([Errno 8] nodename nor servname provided, or not known)

venv/lib/python3.11/site-packages/urllib3/connection.py:203: NameResolutionError

The above exception was the direct cause of the following exception:

self = <requests.adapters.HTTPAdapter object at 0x103944090>, request = <PreparedRequest [POST]>, stream = False, timeout = Timeout(connect=None, read=None, total=None), verify = True, cert = None
proxies = OrderedDict()

def send(
self, request, stream=False, timeout=None, verify=True, cert=None, proxies=None
):
"""Sends PreparedRequest object. Returns Response object.

:param request: The :class:`PreparedRequest <PreparedRequest>` being sent.
:param stream: (optional) Whether to stream the request content.
:param timeout: (optional) How long to wait for the server to send
data before giving up, as a float, or a :ref:`(connect timeout,
read timeout) <timeouts>` tuple.
:type timeout: float or tuple or urllib3 Timeout object
:param verify: (optional) Either a boolean, in which case it controls whether
we verify the server's TLS certificate, or a string, in which case it
must be a path to a CA bundle to use
:param cert: (optional) Any user-provided SSL certificate to be trusted.
:param proxies: (optional) The proxies dictionary to apply to the request.
:rtype: requests.Response
"""

try:
conn = self._get_connection(request, verify, proxies=proxies, cert=cert)
except LocationValueError as e:
raise InvalidURL(e, request=request)

self.cert_verify(conn, request.url, verify, cert)
url = self.request_url(request, proxies)
self.add_headers(
request,
stream=stream,
timeout=timeout,
verify=verify,
cert=cert,
proxies=proxies,
)

chunked = not (request.body is None or "Content-Length" in request.headers)

if isinstance(timeout, tuple):
try:
connect, read = timeout
timeout = TimeoutSauce(connect=connect, read=read)
except ValueError:
raise ValueError(
f"Invalid timeout {timeout}. Pass a (connect, read) timeout tuple, "
f"or a single float to set both timeouts to the same value."
)
elif isinstance(timeout, TimeoutSauce):
pass
else:
timeout = TimeoutSauce(connect=timeout, read=timeout)

try:
> resp = conn.urlopen(
method=request.method,
url=url,
body=request.body,
headers=request.headers,
redirect=False,
assert_same_host=False,
preload_content=False,
decode_content=False,
retries=self.max_retries,
timeout=timeout,
chunked=chunked,
)

venv/lib/python3.11/site-packages/requests/adapters.py:564:
_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _
venv/lib/python3.11/site-packages/urllib3/connectionpool.py:843: in urlopen
retries = retries.increment(
_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _

self = Retry(total=0, connect=None, read=False, redirect=None, status=None), method = 'POST', url = '/api/v5/addons/upload/', response = None
error = NameResolutionError("<urllib3.connection.HTTPSConnection object at 0x103713110>: Failed to resolve 'addons.allizom.org' ([Errno 8] nodename nor servname provided, or not known)")
_pool = <urllib3.connectionpool.HTTPSConnectionPool object at 0x1037107d0>, _stacktrace = <traceback object at 0x103711600>

def increment(
self,
method: str | None = None,
url: str | None = None,
response: BaseHTTPResponse | None = None,
error: Exception | None = None,
_pool: ConnectionPool | None = None,
_stacktrace: TracebackType | None = None,
) -> Self:
"""Return a new Retry object with incremented retry counters.

:param response: A response object, or None, if the server did not
return a response.
:type response: :class:`~urllib3.response.BaseHTTPResponse`
:param Exception error: An error encountered during the request, or
None if the response was received successfully.

:return: A new ``Retry`` object.
"""
if self.total is False and error:
# Disabled, indicate to re-raise the error.
raise reraise(type(error), error, _stacktrace)

total = self.total
if total is not None:
total -= 1

connect = self.connect
read = self.read
redirect = self.redirect
status_count = self.status
other = self.other
cause = "unknown"
status = None
redirect_location = None

if error and self._is_connection_error(error):
# Connect retry?
if connect is False:
raise reraise(type(error), error, _stacktrace)
elif connect is not None:
connect -= 1

elif error and self._is_read_error(error):
# Read retry?
if read is False or method is None or not self._is_method_retryable(method):
raise reraise(type(error), error, _stacktrace)
elif read is not None:
read -= 1

elif error:
# Other retry?
if other is not None:
other -= 1

elif response and response.get_redirect_location():
# Redirect retry?
if redirect is not None:
redirect -= 1
cause = "too many redirects"
response_redirect_location = response.get_redirect_location()
if response_redirect_location:
redirect_location = response_redirect_location
status = response.status

else:
# Incrementing because of a server error like a 500 in
# status_forcelist and the given method is in the allowed_methods
cause = ResponseError.GENERIC_ERROR
if response and response.status:
if status_count is not None:
status_count -= 1
cause = ResponseError.SPECIFIC_ERROR.format(status_code=response.status)
status = response.status

history = self.history + (
RequestHistory(method, url, error, status, redirect_location),
)

new_retry = self.new(
total=total,
connect=connect,
read=read,
redirect=redirect,
status=status_count,
other=other,
history=history,
)

if new_retry.is_exhausted():
reason = error or ResponseError(cause)
> raise MaxRetryError(_pool, url, reason) from reason # type: ignore[arg-type]
E urllib3.exceptions.MaxRetryError: HTTPSConnectionPool(host='addons.allizom.org', port=443): Max retries exceeded with url: /api/v5/addons/upload/ (Caused by NameResolutionError("<urllib3.connection.HTTPSConnection object at 0x103713110>: Failed to resolve 'addons.allizom.org' ([Errno 8] nodename nor servname provided, or not known)"))

venv/lib/python3.11/site-packages/urllib3/util/retry.py:519: MaxRetryError

During handling of the above exception, another exception occurred:

base_url = 'https://addons.allizom.org', session_auth = 'ldvd5ag27bkfpukx6rn2lcj0yuvakt3v'

@pytest.mark.serial
@pytest.mark.create_session("api_user")
def test_upload_addon_with_guid_from_deleted_addon(base_url, session_auth):
"""Create an addon, delete it and then try to reuse the GUID to submit a
new addon; the request should fail since GUIDs cannot be reused"""
guid = f"reused-guid@{reusables.get_random_string(6)}"
# create the addon manifest to be uploaded
manifest = {
**payloads.minimal_manifest,
"name": "Reuse GUID of deleted addon",
"browser_specific_settings": {"gecko": {"id": guid}},
}
api_helpers.make_addon(manifest)
# upload the addon with the custom GUID for the first time
with open("sample-addons/make-addon.zip", "rb") as file:
> upload = requests.post(
url=f"{base_url}{_upload}",
headers={"Authorization": f"Session {session_auth}"},
files={"upload": file},
data={"channel": "unlisted"},
)

tests/api_w/test_addon_uploads.py:957:
_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _
venv/lib/python3.11/site-packages/requests/api.py:115: in post
return request("post", url, data=data, json=json, **kwargs)
venv/lib/python3.11/site-packages/requests/api.py:59: in request
return session.request(method=method, url=url, **kwargs)
venv/lib/python3.11/site-packages/requests/sessions.py:589: in request
resp = self.send(prep, **send_kwargs)
venv/lib/python3.11/site-packages/requests/sessions.py:703: in send
r = adapter.send(request, **kwargs)
_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _

self = <requests.adapters.HTTPAdapter object at 0x103944090>, request = <PreparedRequest [POST]>, stream = False, timeout = Timeout(connect=None, read=None, total=None), verify = True, cert = None
proxies = OrderedDict()

def send(
self, request, stream=False, timeout=None, verify=True, cert=None, proxies=None
):
"""Sends PreparedRequest object. Returns Response object.

:param request: The :class:`PreparedRequest <PreparedRequest>` being sent.
:param stream: (optional) Whether to stream the request content.
:param timeout: (optional) How long to wait for the server to send
data before giving up, as a float, or a :ref:`(connect timeout,
read timeout) <timeouts>` tuple.
:type timeout: float or tuple or urllib3 Timeout object
:param verify: (optional) Either a boolean, in which case it controls whether
we verify the server's TLS certificate, or a string, in which case it
must be a path to a CA bundle to use
:param cert: (optional) Any user-provided SSL certificate to be trusted.
:param proxies: (optional) The proxies dictionary to apply to the request.
:rtype: requests.Response
"""

try:
conn = self._get_connection(request, verify, proxies=proxies, cert=cert)
except LocationValueError as e:
raise InvalidURL(e, request=request)

self.cert_verify(conn, request.url, verify, cert)
url = self.request_url(request, proxies)
self.add_headers(
request,
stream=stream,
timeout=timeout,
verify=verify,
cert=cert,
proxies=proxies,
)

chunked = not (request.body is None or "Content-Length" in request.headers)

if isinstance(timeout, tuple):
try:
connect, read = timeout
timeout = TimeoutSauce(connect=connect, read=read)
except ValueError:
raise ValueError(
f"Invalid timeout {timeout}. Pass a (connect, read) timeout tuple, "
f"or a single float to set both timeouts to the same value."
)
elif isinstance(timeout, TimeoutSauce):
pass
else:
timeout = TimeoutSauce(connect=timeout, read=timeout)

try:
resp = conn.urlopen(
method=request.method,
url=url,
body=request.body,
headers=request.headers,
redirect=False,
assert_same_host=False,
preload_content=False,
decode_content=False,
retries=self.max_retries,
timeout=timeout,
chunked=chunked,
)

except (ProtocolError, OSError) as err:
raise ConnectionError(err, request=request)

except MaxRetryError as e:
if isinstance(e.reason, ConnectTimeoutError):
# TODO: Remove this in 3.0.0: see #2811
if not isinstance(e.reason, NewConnectionError):
raise ConnectTimeout(e, request=request)

if isinstance(e.reason, ResponseError):
raise RetryError(e, request=request)

if isinstance(e.reason, _ProxyError):
raise ProxyError(e, request=request)

if isinstance(e.reason, _SSLError):
# This branch is for urllib3 v1.22 and later.
raise SSLError(e, request=request)

> raise ConnectionError(e, request=request)
E requests.exceptions.ConnectionError: HTTPSConnectionPool(host='addons.allizom.org', port=443): Max retries exceeded with url: /api/v5/addons/upload/ (Caused by NameResolutionError("<urllib3.connection.HTTPSConnection object at 0x103713110>: Failed to resolve 'addons.allizom.org' ([Errno 8] nodename nor servname provided, or not known)"))

venv/lib/python3.11/site-packages/requests/adapters.py:597: ConnectionError
------------------------------Captured stdout call------------------------------
Manifest content: {'manifest_version': 2, 'version': '1.0', 'name': 'Reuse GUID of deleted addon', 'browser_specific_settings': {'gecko': {'id': 'reused-guid@lpbiqk'}}}
Failed tests/api_w/test_addon_uploads.py::test_upload_theme 0.00
self = <urllib3.connection.HTTPSConnection object at 0x103f28ed0>

def _new_conn(self) -> socket.socket:
"""Establish a socket connection and set nodelay settings on it.

:return: New socket connection.
"""
try:
> sock = connection.create_connection(
(self._dns_host, self.port),
self.timeout,
source_address=self.source_address,
socket_options=self.socket_options,
)

venv/lib/python3.11/site-packages/urllib3/connection.py:196:
_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _
venv/lib/python3.11/site-packages/urllib3/util/connection.py:60: in create_connection
for res in socket.getaddrinfo(host, port, family, socket.SOCK_STREAM):
_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _

host = 'addons.allizom.org', port = 443, family = <AddressFamily.AF_UNSPEC: 0>, type = <SocketKind.SOCK_STREAM: 1>, proto = 0, flags = 0

def getaddrinfo(host, port, family=0, type=0, proto=0, flags=0):
"""Resolve host and port into list of address info entries.

Translate the host/port argument into a sequence of 5-tuples that contain
all the necessary arguments for creating a socket connected to that service.
host is a domain name, a string representation of an IPv4/v6 address or
None. port is a string service name such as 'http', a numeric port number or
None. By passing None as the value of host and port, you can pass NULL to
the underlying C API.

The family, type and proto arguments can be optionally specified in order to
narrow the list of addresses returned. Passing zero as a value for each of
these arguments selects the full range of results.
"""
# We override this function since we want to translate the numeric family
# and socket type values to enum constants.
addrlist = []
> for res in _socket.getaddrinfo(host, port, family, type, proto, flags):
E socket.gaierror: [Errno 8] nodename nor servname provided, or not known

/Library/Frameworks/Python.framework/Versions/3.11/lib/python3.11/socket.py:962: gaierror

The above exception was the direct cause of the following exception:

self = <urllib3.connectionpool.HTTPSConnectionPool object at 0x103f29cd0>, method = 'POST', url = '/api/v5/addons/upload/'
body = b'--29a306c179c2816846f3a63cde303d21\r\nContent-Disposition: form-data; name="channel"\r\n\r\nlisted\r\n--29a306c179c2...06\x00\x00\x00\x00\x02\x00\x02\x00\xbf\x00\x00\x00\xe9\x02\x00\x00\x00\x00\r\n--29a306c179c2816846f3a63cde303d21--\r\n'
headers = {'User-Agent': 'python-requests/2.32.0', 'Accept-Encoding': 'gzip, deflate', 'Accept': '*/*', 'Connection': 'keep-aliv...0yuvakt3v', 'Content-Length': '1199', 'Content-Type': 'multipart/form-data; boundary=29a306c179c2816846f3a63cde303d21'}
retries = Retry(total=0, connect=None, read=False, redirect=None, status=None), redirect = False, assert_same_host = False, timeout = Timeout(connect=None, read=None, total=None), pool_timeout = None
release_conn = False, chunked = False, body_pos = None, preload_content = False, decode_content = False, response_kw = {}
parsed_url = Url(scheme=None, auth=None, host=None, port=None, path='/api/v5/addons/upload/', query=None, fragment=None), destination_scheme = None, conn = None, release_this_conn = True
http_tunnel_required = False, err = None, clean_exit = False

def urlopen( # type: ignore[override]
self,
method: str,
url: str,
body: _TYPE_BODY | None = None,
headers: typing.Mapping[str, str] | None = None,
retries: Retry | bool | int | None = None,
redirect: bool = True,
assert_same_host: bool = True,
timeout: _TYPE_TIMEOUT = _DEFAULT_TIMEOUT,
pool_timeout: int | None = None,
release_conn: bool | None = None,
chunked: bool = False,
body_pos: _TYPE_BODY_POSITION | None = None,
preload_content: bool = True,
decode_content: bool = True,
**response_kw: typing.Any,
) -> BaseHTTPResponse:
"""
Get a connection from the pool and perform an HTTP request. This is the
lowest level call for making a request, so you'll need to specify all
the raw details.

.. note::

More commonly, it's appropriate to use a convenience method
such as :meth:`request`.

.. note::

`release_conn` will only behave as expected if
`preload_content=False` because we want to make
`preload_content=False` the default behaviour someday soon without
breaking backwards compatibility.

:param method:
HTTP request method (such as GET, POST, PUT, etc.)

:param url:
The URL to perform the request on.

:param body:
Data to send in the request body, either :class:`str`, :class:`bytes`,
an iterable of :class:`str`/:class:`bytes`, or a file-like object.

:param headers:
Dictionary of custom headers to send, such as User-Agent,
If-None-Match, etc. If None, pool headers are used. If provided,
these headers completely replace any pool-specific headers.

:param retries:
Configure the number of retries to allow before raising a
:class:`~urllib3.exceptions.MaxRetryError` exception.

If ``None`` (default) will retry 3 times, see ``Retry.DEFAULT``. Pass a
:class:`~urllib3.util.retry.Retry` object for fine-grained control
over different types of retries.
Pass an integer number to retry connection errors that many times,
but no other types of errors. Pass zero to never retry.

If ``False``, then retries are disabled and any exception is raised
immediately. Also, instead of raising a MaxRetryError on redirects,
the redirect response will be returned.

:type retries: :class:`~urllib3.util.retry.Retry`, False, or an int.

:param redirect:
If True, automatically handle redirects (status codes 301, 302,
303, 307, 308). Each redirect counts as a retry. Disabling retries
will disable redirect, too.

:param assert_same_host:
If ``True``, will make sure that the host of the pool requests is
consistent else will raise HostChangedError. When ``False``, you can
use the pool on an HTTP proxy and request foreign hosts.

:param timeout:
If specified, overrides the default timeout for this one
request. It may be a float (in seconds) or an instance of
:class:`urllib3.util.Timeout`.

:param pool_timeout:
If set and the pool is set to block=True, then this method will
block for ``pool_timeout`` seconds and raise EmptyPoolError if no
connection is available within the time period.

:param bool preload_content:
If True, the response's body will be preloaded into memory.

:param bool decode_content:
If True, will attempt to decode the body based on the
'content-encoding' header.

:param release_conn:
If False, then the urlopen call will not release the connection
back into the pool once a response is received (but will release if
you read the entire contents of the response such as when
`preload_content=True`). This is useful if you're not preloading
the response's content immediately. You will need to call
``r.release_conn()`` on the response ``r`` to return the connection
back into the pool. If None, it takes the value of ``preload_content``
which defaults to ``True``.

:param bool chunked:
If True, urllib3 will send the body using chunked transfer
encoding. Otherwise, urllib3 will send the body using the standard
content-length form. Defaults to False.

:param int body_pos:
Position to seek to in file-like body in the event of a retry or
redirect. Typically this won't need to be set because urllib3 will
auto-populate the value when needed.
"""
parsed_url = parse_url(url)
destination_scheme = parsed_url.scheme

if headers is None:
headers = self.headers

if not isinstance(retries, Retry):
retries = Retry.from_int(retries, redirect=redirect, default=self.retries)

if release_conn is None:
release_conn = preload_content

# Check host
if assert_same_host and not self.is_same_host(url):
raise HostChangedError(self, url, retries)

# Ensure that the URL we're connecting to is properly encoded
if url.startswith("/"):
url = to_str(_encode_target(url))
else:
url = to_str(parsed_url.url)

conn = None

# Track whether `conn` needs to be released before
# returning/raising/recursing. Update this variable if necessary, and
# leave `release_conn` constant throughout the function. That way, if
# the function recurses, the original value of `release_conn` will be
# passed down into the recursive call, and its value will be respected.
#
# See issue #651 [1] for details.
#
# [1] <https://github.com/urllib3/urllib3/issues/651>
release_this_conn = release_conn

http_tunnel_required = connection_requires_http_tunnel(
self.proxy, self.proxy_config, destination_scheme
)

# Merge the proxy headers. Only done when not using HTTP CONNECT. We
# have to copy the headers dict so we can safely change it without those
# changes being reflected in anyone else's copy.
if not http_tunnel_required:
headers = headers.copy() # type: ignore[attr-defined]
headers.update(self.proxy_headers) # type: ignore[union-attr]

# Must keep the exception bound to a separate variable or else Python 3
# complains about UnboundLocalError.
err = None

# Keep track of whether we cleanly exited the except block. This
# ensures we do proper cleanup in finally.
clean_exit = False

# Rewind body position, if needed. Record current position
# for future rewinds in the event of a redirect/retry.
body_pos = set_file_position(body, body_pos)

try:
# Request a connection from the queue.
timeout_obj = self._get_timeout(timeout)
conn = self._get_conn(timeout=pool_timeout)

conn.timeout = timeout_obj.connect_timeout # type: ignore[assignment]

# Is this a closed/new connection that requires CONNECT tunnelling?
if self.proxy is not None and http_tunnel_required and conn.is_closed:
try:
self._prepare_proxy(conn)
except (BaseSSLError, OSError, SocketTimeout) as e:
self._raise_timeout(
err=e, url=self.proxy.url, timeout_value=conn.timeout
)
raise

# If we're going to release the connection in ``finally:``, then
# the response doesn't need to know about the connection. Otherwise
# it will also try to release it and we'll have a double-release
# mess.
response_conn = conn if not release_conn else None

# Make the request on the HTTPConnection object
> response = self._make_request(
conn,
method,
url,
timeout=timeout_obj,
body=body,
headers=headers,
chunked=chunked,
retries=retries,
response_conn=response_conn,
preload_content=preload_content,
decode_content=decode_content,
**response_kw,
)

venv/lib/python3.11/site-packages/urllib3/connectionpool.py:789:
_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _
venv/lib/python3.11/site-packages/urllib3/connectionpool.py:490: in _make_request
raise new_e
venv/lib/python3.11/site-packages/urllib3/connectionpool.py:466: in _make_request
self._validate_conn(conn)
venv/lib/python3.11/site-packages/urllib3/connectionpool.py:1095: in _validate_conn
conn.connect()
venv/lib/python3.11/site-packages/urllib3/connection.py:615: in connect
self.sock = sock = self._new_conn()
_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _

self = <urllib3.connection.HTTPSConnection object at 0x103f28ed0>

def _new_conn(self) -> socket.socket:
"""Establish a socket connection and set nodelay settings on it.

:return: New socket connection.
"""
try:
sock = connection.create_connection(
(self._dns_host, self.port),
self.timeout,
source_address=self.source_address,
socket_options=self.socket_options,
)
except socket.gaierror as e:
> raise NameResolutionError(self.host, self, e) from e
E urllib3.exceptions.NameResolutionError: <urllib3.connection.HTTPSConnection object at 0x103f28ed0>: Failed to resolve 'addons.allizom.org' ([Errno 8] nodename nor servname provided, or not known)

venv/lib/python3.11/site-packages/urllib3/connection.py:203: NameResolutionError

The above exception was the direct cause of the following exception:

self = <requests.adapters.HTTPAdapter object at 0x103bf5110>, request = <PreparedRequest [POST]>, stream = False, timeout = Timeout(connect=None, read=None, total=None), verify = True, cert = None
proxies = OrderedDict()

def send(
self, request, stream=False, timeout=None, verify=True, cert=None, proxies=None
):
"""Sends PreparedRequest object. Returns Response object.

:param request: The :class:`PreparedRequest <PreparedRequest>` being sent.
:param stream: (optional) Whether to stream the request content.
:param timeout: (optional) How long to wait for the server to send
data before giving up, as a float, or a :ref:`(connect timeout,
read timeout) <timeouts>` tuple.
:type timeout: float or tuple or urllib3 Timeout object
:param verify: (optional) Either a boolean, in which case it controls whether
we verify the server's TLS certificate, or a string, in which case it
must be a path to a CA bundle to use
:param cert: (optional) Any user-provided SSL certificate to be trusted.
:param proxies: (optional) The proxies dictionary to apply to the request.
:rtype: requests.Response
"""

try:
conn = self._get_connection(request, verify, proxies=proxies, cert=cert)
except LocationValueError as e:
raise InvalidURL(e, request=request)

self.cert_verify(conn, request.url, verify, cert)
url = self.request_url(request, proxies)
self.add_headers(
request,
stream=stream,
timeout=timeout,
verify=verify,
cert=cert,
proxies=proxies,
)

chunked = not (request.body is None or "Content-Length" in request.headers)

if isinstance(timeout, tuple):
try:
connect, read = timeout
timeout = TimeoutSauce(connect=connect, read=read)
except ValueError:
raise ValueError(
f"Invalid timeout {timeout}. Pass a (connect, read) timeout tuple, "
f"or a single float to set both timeouts to the same value."
)
elif isinstance(timeout, TimeoutSauce):
pass
else:
timeout = TimeoutSauce(connect=timeout, read=timeout)

try:
> resp = conn.urlopen(
method=request.method,
url=url,
body=request.body,
headers=request.headers,
redirect=False,
assert_same_host=False,
preload_content=False,
decode_content=False,
retries=self.max_retries,
timeout=timeout,
chunked=chunked,
)

venv/lib/python3.11/site-packages/requests/adapters.py:564:
_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _
venv/lib/python3.11/site-packages/urllib3/connectionpool.py:843: in urlopen
retries = retries.increment(
_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _

self = Retry(total=0, connect=None, read=False, redirect=None, status=None), method = 'POST', url = '/api/v5/addons/upload/', response = None
error = NameResolutionError("<urllib3.connection.HTTPSConnection object at 0x103f28ed0>: Failed to resolve 'addons.allizom.org' ([Errno 8] nodename nor servname provided, or not known)")
_pool = <urllib3.connectionpool.HTTPSConnectionPool object at 0x103f29cd0>, _stacktrace = <traceback object at 0x103f29fc0>

def increment(
self,
method: str | None = None,
url: str | None = None,
response: BaseHTTPResponse | None = None,
error: Exception | None = None,
_pool: ConnectionPool | None = None,
_stacktrace: TracebackType | None = None,
) -> Self:
"""Return a new Retry object with incremented retry counters.

:param response: A response object, or None, if the server did not
return a response.
:type response: :class:`~urllib3.response.BaseHTTPResponse`
:param Exception error: An error encountered during the request, or
None if the response was received successfully.

:return: A new ``Retry`` object.
"""
if self.total is False and error:
# Disabled, indicate to re-raise the error.
raise reraise(type(error), error, _stacktrace)

total = self.total
if total is not None:
total -= 1

connect = self.connect
read = self.read
redirect = self.redirect
status_count = self.status
other = self.other
cause = "unknown"
status = None
redirect_location = None

if error and self._is_connection_error(error):
# Connect retry?
if connect is False:
raise reraise(type(error), error, _stacktrace)
elif connect is not None:
connect -= 1

elif error and self._is_read_error(error):
# Read retry?
if read is False or method is None or not self._is_method_retryable(method):
raise reraise(type(error), error, _stacktrace)
elif read is not None:
read -= 1

elif error:
# Other retry?
if other is not None:
other -= 1

elif response and response.get_redirect_location():
# Redirect retry?
if redirect is not None:
redirect -= 1
cause = "too many redirects"
response_redirect_location = response.get_redirect_location()
if response_redirect_location:
redirect_location = response_redirect_location
status = response.status

else:
# Incrementing because of a server error like a 500 in
# status_forcelist and the given method is in the allowed_methods
cause = ResponseError.GENERIC_ERROR
if response and response.status:
if status_count is not None:
status_count -= 1
cause = ResponseError.SPECIFIC_ERROR.format(status_code=response.status)
status = response.status

history = self.history + (
RequestHistory(method, url, error, status, redirect_location),
)

new_retry = self.new(
total=total,
connect=connect,
read=read,
redirect=redirect,
status=status_count,
other=other,
history=history,
)

if new_retry.is_exhausted():
reason = error or ResponseError(cause)
> raise MaxRetryError(_pool, url, reason) from reason # type: ignore[arg-type]
E urllib3.exceptions.MaxRetryError: HTTPSConnectionPool(host='addons.allizom.org', port=443): Max retries exceeded with url: /api/v5/addons/upload/ (Caused by NameResolutionError("<urllib3.connection.HTTPSConnection object at 0x103f28ed0>: Failed to resolve 'addons.allizom.org' ([Errno 8] nodename nor servname provided, or not known)"))

venv/lib/python3.11/site-packages/urllib3/util/retry.py:519: MaxRetryError

During handling of the above exception, another exception occurred:

base_url = 'https://addons.allizom.org', session_auth = 'ldvd5ag27bkfpukx6rn2lcj0yuvakt3v'

@pytest.mark.serial
@pytest.mark.create_session("api_user")
def test_upload_theme(base_url, session_auth):
with open("sample-addons/theme.xpi", "rb") as file:
> upload = requests.post(
url=f"{base_url}{_upload}",
headers={"Authorization": f"Session {session_auth}"},
files={"upload": file},
data={"channel": "listed"},
)

tests/api_w/test_addon_uploads.py:1027:
_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _
venv/lib/python3.11/site-packages/requests/api.py:115: in post
return request("post", url, data=data, json=json, **kwargs)
venv/lib/python3.11/site-packages/requests/api.py:59: in request
return session.request(method=method, url=url, **kwargs)
venv/lib/python3.11/site-packages/requests/sessions.py:589: in request
resp = self.send(prep, **send_kwargs)
venv/lib/python3.11/site-packages/requests/sessions.py:703: in send
r = adapter.send(request, **kwargs)
_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _

self = <requests.adapters.HTTPAdapter object at 0x103bf5110>, request = <PreparedRequest [POST]>, stream = False, timeout = Timeout(connect=None, read=None, total=None), verify = True, cert = None
proxies = OrderedDict()

def send(
self, request, stream=False, timeout=None, verify=True, cert=None, proxies=None
):
"""Sends PreparedRequest object. Returns Response object.

:param request: The :class:`PreparedRequest <PreparedRequest>` being sent.
:param stream: (optional) Whether to stream the request content.
:param timeout: (optional) How long to wait for the server to send
data before giving up, as a float, or a :ref:`(connect timeout,
read timeout) <timeouts>` tuple.
:type timeout: float or tuple or urllib3 Timeout object
:param verify: (optional) Either a boolean, in which case it controls whether
we verify the server's TLS certificate, or a string, in which case it
must be a path to a CA bundle to use
:param cert: (optional) Any user-provided SSL certificate to be trusted.
:param proxies: (optional) The proxies dictionary to apply to the request.
:rtype: requests.Response
"""

try:
conn = self._get_connection(request, verify, proxies=proxies, cert=cert)
except LocationValueError as e:
raise InvalidURL(e, request=request)

self.cert_verify(conn, request.url, verify, cert)
url = self.request_url(request, proxies)
self.add_headers(
request,
stream=stream,
timeout=timeout,
verify=verify,
cert=cert,
proxies=proxies,
)

chunked = not (request.body is None or "Content-Length" in request.headers)

if isinstance(timeout, tuple):
try:
connect, read = timeout
timeout = TimeoutSauce(connect=connect, read=read)
except ValueError:
raise ValueError(
f"Invalid timeout {timeout}. Pass a (connect, read) timeout tuple, "
f"or a single float to set both timeouts to the same value."
)
elif isinstance(timeout, TimeoutSauce):
pass
else:
timeout = TimeoutSauce(connect=timeout, read=timeout)

try:
resp = conn.urlopen(
method=request.method,
url=url,
body=request.body,
headers=request.headers,
redirect=False,
assert_same_host=False,
preload_content=False,
decode_content=False,
retries=self.max_retries,
timeout=timeout,
chunked=chunked,
)

except (ProtocolError, OSError) as err:
raise ConnectionError(err, request=request)

except MaxRetryError as e:
if isinstance(e.reason, ConnectTimeoutError):
# TODO: Remove this in 3.0.0: see #2811
if not isinstance(e.reason, NewConnectionError):
raise ConnectTimeout(e, request=request)

if isinstance(e.reason, ResponseError):
raise RetryError(e, request=request)

if isinstance(e.reason, _ProxyError):
raise ProxyError(e, request=request)

if isinstance(e.reason, _SSLError):
# This branch is for urllib3 v1.22 and later.
raise SSLError(e, request=request)

> raise ConnectionError(e, request=request)
E requests.exceptions.ConnectionError: HTTPSConnectionPool(host='addons.allizom.org', port=443): Max retries exceeded with url: /api/v5/addons/upload/ (Caused by NameResolutionError("<urllib3.connection.HTTPSConnection object at 0x103f28ed0>: Failed to resolve 'addons.allizom.org' ([Errno 8] nodename nor servname provided, or not known)"))

venv/lib/python3.11/site-packages/requests/adapters.py:597: ConnectionError
Failed tests/api_w/test_addon_uploads.py::test_upload_theme_with_wrong_license 0.00
self = <urllib3.connection.HTTPSConnection object at 0x103d8c710>

def _new_conn(self) -> socket.socket:
"""Establish a socket connection and set nodelay settings on it.

:return: New socket connection.
"""
try:
> sock = connection.create_connection(
(self._dns_host, self.port),
self.timeout,
source_address=self.source_address,
socket_options=self.socket_options,
)

venv/lib/python3.11/site-packages/urllib3/connection.py:196:
_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _
venv/lib/python3.11/site-packages/urllib3/util/connection.py:60: in create_connection
for res in socket.getaddrinfo(host, port, family, socket.SOCK_STREAM):
_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _

host = 'addons.allizom.org', port = 443, family = <AddressFamily.AF_UNSPEC: 0>, type = <SocketKind.SOCK_STREAM: 1>, proto = 0, flags = 0

def getaddrinfo(host, port, family=0, type=0, proto=0, flags=0):
"""Resolve host and port into list of address info entries.

Translate the host/port argument into a sequence of 5-tuples that contain
all the necessary arguments for creating a socket connected to that service.
host is a domain name, a string representation of an IPv4/v6 address or
None. port is a string service name such as 'http', a numeric port number or
None. By passing None as the value of host and port, you can pass NULL to
the underlying C API.

The family, type and proto arguments can be optionally specified in order to
narrow the list of addresses returned. Passing zero as a value for each of
these arguments selects the full range of results.
"""
# We override this function since we want to translate the numeric family
# and socket type values to enum constants.
addrlist = []
> for res in _socket.getaddrinfo(host, port, family, type, proto, flags):
E socket.gaierror: [Errno 8] nodename nor servname provided, or not known

/Library/Frameworks/Python.framework/Versions/3.11/lib/python3.11/socket.py:962: gaierror

The above exception was the direct cause of the following exception:

self = <urllib3.connectionpool.HTTPSConnectionPool object at 0x103d8ef50>, method = 'POST', url = '/api/v5/addons/upload/'
body = b'--3952b501a0a18f5cdf6409ed18e80ade\r\nContent-Disposition: form-data; name="channel"\r\n\r\nlisted\r\n--3952b501a0a1...06\x00\x00\x00\x00\x02\x00\x02\x00\xbf\x00\x00\x00\xe9\x02\x00\x00\x00\x00\r\n--3952b501a0a18f5cdf6409ed18e80ade--\r\n'
headers = {'User-Agent': 'python-requests/2.32.0', 'Accept-Encoding': 'gzip, deflate', 'Accept': '*/*', 'Connection': 'keep-aliv...0yuvakt3v', 'Content-Length': '1199', 'Content-Type': 'multipart/form-data; boundary=3952b501a0a18f5cdf6409ed18e80ade'}
retries = Retry(total=0, connect=None, read=False, redirect=None, status=None), redirect = False, assert_same_host = False, timeout = Timeout(connect=None, read=None, total=None), pool_timeout = None
release_conn = False, chunked = False, body_pos = None, preload_content = False, decode_content = False, response_kw = {}
parsed_url = Url(scheme=None, auth=None, host=None, port=None, path='/api/v5/addons/upload/', query=None, fragment=None), destination_scheme = None, conn = None, release_this_conn = True
http_tunnel_required = False, err = None, clean_exit = False

def urlopen( # type: ignore[override]
self,
method: str,
url: str,
body: _TYPE_BODY | None = None,
headers: typing.Mapping[str, str] | None = None,
retries: Retry | bool | int | None = None,
redirect: bool = True,
assert_same_host: bool = True,
timeout: _TYPE_TIMEOUT = _DEFAULT_TIMEOUT,
pool_timeout: int | None = None,
release_conn: bool | None = None,
chunked: bool = False,
body_pos: _TYPE_BODY_POSITION | None = None,
preload_content: bool = True,
decode_content: bool = True,
**response_kw: typing.Any,
) -> BaseHTTPResponse:
"""
Get a connection from the pool and perform an HTTP request. This is the
lowest level call for making a request, so you'll need to specify all
the raw details.

.. note::

More commonly, it's appropriate to use a convenience method
such as :meth:`request`.

.. note::

`release_conn` will only behave as expected if
`preload_content=False` because we want to make
`preload_content=False` the default behaviour someday soon without
breaking backwards compatibility.

:param method:
HTTP request method (such as GET, POST, PUT, etc.)

:param url:
The URL to perform the request on.

:param body:
Data to send in the request body, either :class:`str`, :class:`bytes`,
an iterable of :class:`str`/:class:`bytes`, or a file-like object.

:param headers:
Dictionary of custom headers to send, such as User-Agent,
If-None-Match, etc. If None, pool headers are used. If provided,
these headers completely replace any pool-specific headers.

:param retries:
Configure the number of retries to allow before raising a
:class:`~urllib3.exceptions.MaxRetryError` exception.

If ``None`` (default) will retry 3 times, see ``Retry.DEFAULT``. Pass a
:class:`~urllib3.util.retry.Retry` object for fine-grained control
over different types of retries.
Pass an integer number to retry connection errors that many times,
but no other types of errors. Pass zero to never retry.

If ``False``, then retries are disabled and any exception is raised
immediately. Also, instead of raising a MaxRetryError on redirects,
the redirect response will be returned.

:type retries: :class:`~urllib3.util.retry.Retry`, False, or an int.

:param redirect:
If True, automatically handle redirects (status codes 301, 302,
303, 307, 308). Each redirect counts as a retry. Disabling retries
will disable redirect, too.

:param assert_same_host:
If ``True``, will make sure that the host of the pool requests is
consistent else will raise HostChangedError. When ``False``, you can
use the pool on an HTTP proxy and request foreign hosts.

:param timeout:
If specified, overrides the default timeout for this one
request. It may be a float (in seconds) or an instance of
:class:`urllib3.util.Timeout`.

:param pool_timeout:
If set and the pool is set to block=True, then this method will
block for ``pool_timeout`` seconds and raise EmptyPoolError if no
connection is available within the time period.

:param bool preload_content:
If True, the response's body will be preloaded into memory.

:param bool decode_content:
If True, will attempt to decode the body based on the
'content-encoding' header.

:param release_conn:
If False, then the urlopen call will not release the connection
back into the pool once a response is received (but will release if
you read the entire contents of the response such as when
`preload_content=True`). This is useful if you're not preloading
the response's content immediately. You will need to call
``r.release_conn()`` on the response ``r`` to return the connection
back into the pool. If None, it takes the value of ``preload_content``
which defaults to ``True``.

:param bool chunked:
If True, urllib3 will send the body using chunked transfer
encoding. Otherwise, urllib3 will send the body using the standard
content-length form. Defaults to False.

:param int body_pos:
Position to seek to in file-like body in the event of a retry or
redirect. Typically this won't need to be set because urllib3 will
auto-populate the value when needed.
"""
parsed_url = parse_url(url)
destination_scheme = parsed_url.scheme

if headers is None:
headers = self.headers

if not isinstance(retries, Retry):
retries = Retry.from_int(retries, redirect=redirect, default=self.retries)

if release_conn is None:
release_conn = preload_content

# Check host
if assert_same_host and not self.is_same_host(url):
raise HostChangedError(self, url, retries)

# Ensure that the URL we're connecting to is properly encoded
if url.startswith("/"):
url = to_str(_encode_target(url))
else:
url = to_str(parsed_url.url)

conn = None

# Track whether `conn` needs to be released before
# returning/raising/recursing. Update this variable if necessary, and
# leave `release_conn` constant throughout the function. That way, if
# the function recurses, the original value of `release_conn` will be
# passed down into the recursive call, and its value will be respected.
#
# See issue #651 [1] for details.
#
# [1] <https://github.com/urllib3/urllib3/issues/651>
release_this_conn = release_conn

http_tunnel_required = connection_requires_http_tunnel(
self.proxy, self.proxy_config, destination_scheme
)

# Merge the proxy headers. Only done when not using HTTP CONNECT. We
# have to copy the headers dict so we can safely change it without those
# changes being reflected in anyone else's copy.
if not http_tunnel_required:
headers = headers.copy() # type: ignore[attr-defined]
headers.update(self.proxy_headers) # type: ignore[union-attr]

# Must keep the exception bound to a separate variable or else Python 3
# complains about UnboundLocalError.
err = None

# Keep track of whether we cleanly exited the except block. This
# ensures we do proper cleanup in finally.
clean_exit = False

# Rewind body position, if needed. Record current position
# for future rewinds in the event of a redirect/retry.
body_pos = set_file_position(body, body_pos)

try:
# Request a connection from the queue.
timeout_obj = self._get_timeout(timeout)
conn = self._get_conn(timeout=pool_timeout)

conn.timeout = timeout_obj.connect_timeout # type: ignore[assignment]

# Is this a closed/new connection that requires CONNECT tunnelling?
if self.proxy is not None and http_tunnel_required and conn.is_closed:
try:
self._prepare_proxy(conn)
except (BaseSSLError, OSError, SocketTimeout) as e:
self._raise_timeout(
err=e, url=self.proxy.url, timeout_value=conn.timeout
)
raise

# If we're going to release the connection in ``finally:``, then
# the response doesn't need to know about the connection. Otherwise
# it will also try to release it and we'll have a double-release
# mess.
response_conn = conn if not release_conn else None

# Make the request on the HTTPConnection object
> response = self._make_request(
conn,
method,
url,
timeout=timeout_obj,
body=body,
headers=headers,
chunked=chunked,
retries=retries,
response_conn=response_conn,
preload_content=preload_content,
decode_content=decode_content,
**response_kw,
)

venv/lib/python3.11/site-packages/urllib3/connectionpool.py:789:
_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _
venv/lib/python3.11/site-packages/urllib3/connectionpool.py:490: in _make_request
raise new_e
venv/lib/python3.11/site-packages/urllib3/connectionpool.py:466: in _make_request
self._validate_conn(conn)
venv/lib/python3.11/site-packages/urllib3/connectionpool.py:1095: in _validate_conn
conn.connect()
venv/lib/python3.11/site-packages/urllib3/connection.py:615: in connect
self.sock = sock = self._new_conn()
_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _

self = <urllib3.connection.HTTPSConnection object at 0x103d8c710>

def _new_conn(self) -> socket.socket:
"""Establish a socket connection and set nodelay settings on it.

:return: New socket connection.
"""
try:
sock = connection.create_connection(
(self._dns_host, self.port),
self.timeout,
source_address=self.source_address,
socket_options=self.socket_options,
)
except socket.gaierror as e:
> raise NameResolutionError(self.host, self, e) from e
E urllib3.exceptions.NameResolutionError: <urllib3.connection.HTTPSConnection object at 0x103d8c710>: Failed to resolve 'addons.allizom.org' ([Errno 8] nodename nor servname provided, or not known)

venv/lib/python3.11/site-packages/urllib3/connection.py:203: NameResolutionError

The above exception was the direct cause of the following exception:

self = <requests.adapters.HTTPAdapter object at 0x103709290>, request = <PreparedRequest [POST]>, stream = False, timeout = Timeout(connect=None, read=None, total=None), verify = True, cert = None
proxies = OrderedDict()

def send(
self, request, stream=False, timeout=None, verify=True, cert=None, proxies=None
):
"""Sends PreparedRequest object. Returns Response object.

:param request: The :class:`PreparedRequest <PreparedRequest>` being sent.
:param stream: (optional) Whether to stream the request content.
:param timeout: (optional) How long to wait for the server to send
data before giving up, as a float, or a :ref:`(connect timeout,
read timeout) <timeouts>` tuple.
:type timeout: float or tuple or urllib3 Timeout object
:param verify: (optional) Either a boolean, in which case it controls whether
we verify the server's TLS certificate, or a string, in which case it
must be a path to a CA bundle to use
:param cert: (optional) Any user-provided SSL certificate to be trusted.
:param proxies: (optional) The proxies dictionary to apply to the request.
:rtype: requests.Response
"""

try:
conn = self._get_connection(request, verify, proxies=proxies, cert=cert)
except LocationValueError as e:
raise InvalidURL(e, request=request)

self.cert_verify(conn, request.url, verify, cert)
url = self.request_url(request, proxies)
self.add_headers(
request,
stream=stream,
timeout=timeout,
verify=verify,
cert=cert,
proxies=proxies,
)

chunked = not (request.body is None or "Content-Length" in request.headers)

if isinstance(timeout, tuple):
try:
connect, read = timeout
timeout = TimeoutSauce(connect=connect, read=read)
except ValueError:
raise ValueError(
f"Invalid timeout {timeout}. Pass a (connect, read) timeout tuple, "
f"or a single float to set both timeouts to the same value."
)
elif isinstance(timeout, TimeoutSauce):
pass
else:
timeout = TimeoutSauce(connect=timeout, read=timeout)

try:
> resp = conn.urlopen(
method=request.method,
url=url,
body=request.body,
headers=request.headers,
redirect=False,
assert_same_host=False,
preload_content=False,
decode_content=False,
retries=self.max_retries,
timeout=timeout,
chunked=chunked,
)

venv/lib/python3.11/site-packages/requests/adapters.py:564:
_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _
venv/lib/python3.11/site-packages/urllib3/connectionpool.py:843: in urlopen
retries = retries.increment(
_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _

self = Retry(total=0, connect=None, read=False, redirect=None, status=None), method = 'POST', url = '/api/v5/addons/upload/', response = None
error = NameResolutionError("<urllib3.connection.HTTPSConnection object at 0x103d8c710>: Failed to resolve 'addons.allizom.org' ([Errno 8] nodename nor servname provided, or not known)")
_pool = <urllib3.connectionpool.HTTPSConnectionPool object at 0x103d8ef50>, _stacktrace = <traceback object at 0x103d8f240>

def increment(
self,
method: str | None = None,
url: str | None = None,
response: BaseHTTPResponse | None = None,
error: Exception | None = None,
_pool: ConnectionPool | None = None,
_stacktrace: TracebackType | None = None,
) -> Self:
"""Return a new Retry object with incremented retry counters.

:param response: A response object, or None, if the server did not
return a response.
:type response: :class:`~urllib3.response.BaseHTTPResponse`
:param Exception error: An error encountered during the request, or
None if the response was received successfully.

:return: A new ``Retry`` object.
"""
if self.total is False and error:
# Disabled, indicate to re-raise the error.
raise reraise(type(error), error, _stacktrace)

total = self.total
if total is not None:
total -= 1

connect = self.connect
read = self.read
redirect = self.redirect
status_count = self.status
other = self.other
cause = "unknown"
status = None
redirect_location = None

if error and self._is_connection_error(error):
# Connect retry?
if connect is False:
raise reraise(type(error), error, _stacktrace)
elif connect is not None:
connect -= 1

elif error and self._is_read_error(error):
# Read retry?
if read is False or method is None or not self._is_method_retryable(method):
raise reraise(type(error), error, _stacktrace)
elif read is not None:
read -= 1

elif error:
# Other retry?
if other is not None:
other -= 1

elif response and response.get_redirect_location():
# Redirect retry?
if redirect is not None:
redirect -= 1
cause = "too many redirects"
response_redirect_location = response.get_redirect_location()
if response_redirect_location:
redirect_location = response_redirect_location
status = response.status

else:
# Incrementing because of a server error like a 500 in
# status_forcelist and the given method is in the allowed_methods
cause = ResponseError.GENERIC_ERROR
if response and response.status:
if status_count is not None:
status_count -= 1
cause = ResponseError.SPECIFIC_ERROR.format(status_code=response.status)
status = response.status

history = self.history + (
RequestHistory(method, url, error, status, redirect_location),
)

new_retry = self.new(
total=total,
connect=connect,
read=read,
redirect=redirect,
status=status_count,
other=other,
history=history,
)

if new_retry.is_exhausted():
reason = error or ResponseError(cause)
> raise MaxRetryError(_pool, url, reason) from reason # type: ignore[arg-type]
E urllib3.exceptions.MaxRetryError: HTTPSConnectionPool(host='addons.allizom.org', port=443): Max retries exceeded with url: /api/v5/addons/upload/ (Caused by NameResolutionError("<urllib3.connection.HTTPSConnection object at 0x103d8c710>: Failed to resolve 'addons.allizom.org' ([Errno 8] nodename nor servname provided, or not known)"))

venv/lib/python3.11/site-packages/urllib3/util/retry.py:519: MaxRetryError

During handling of the above exception, another exception occurred:

base_url = 'https://addons.allizom.org', session_auth = 'ldvd5ag27bkfpukx6rn2lcj0yuvakt3v'

@pytest.mark.serial
@pytest.mark.create_session("api_user")
def test_upload_theme_with_wrong_license(base_url, session_auth):
"""Try to upload a theme while using a license that is specific for extensions"""
with open("sample-addons/theme.xpi", "rb") as file:
> upload = requests.post(
url=f"{base_url}{_upload}",
headers={"Authorization": f"Session {session_auth}"},
files={"upload": file},
data={"channel": "listed"},
)

tests/api_w/test_addon_uploads.py:1067:
_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _
venv/lib/python3.11/site-packages/requests/api.py:115: in post
return request("post", url, data=data, json=json, **kwargs)
venv/lib/python3.11/site-packages/requests/api.py:59: in request
return session.request(method=method, url=url, **kwargs)
venv/lib/python3.11/site-packages/requests/sessions.py:589: in request
resp = self.send(prep, **send_kwargs)
venv/lib/python3.11/site-packages/requests/sessions.py:703: in send
r = adapter.send(request, **kwargs)
_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _

self = <requests.adapters.HTTPAdapter object at 0x103709290>, request = <PreparedRequest [POST]>, stream = False, timeout = Timeout(connect=None, read=None, total=None), verify = True, cert = None
proxies = OrderedDict()

def send(
self, request, stream=False, timeout=None, verify=True, cert=None, proxies=None
):
"""Sends PreparedRequest object. Returns Response object.

:param request: The :class:`PreparedRequest <PreparedRequest>` being sent.
:param stream: (optional) Whether to stream the request content.
:param timeout: (optional) How long to wait for the server to send
data before giving up, as a float, or a :ref:`(connect timeout,
read timeout) <timeouts>` tuple.
:type timeout: float or tuple or urllib3 Timeout object
:param verify: (optional) Either a boolean, in which case it controls whether
we verify the server's TLS certificate, or a string, in which case it
must be a path to a CA bundle to use
:param cert: (optional) Any user-provided SSL certificate to be trusted.
:param proxies: (optional) The proxies dictionary to apply to the request.
:rtype: requests.Response
"""

try:
conn = self._get_connection(request, verify, proxies=proxies, cert=cert)
except LocationValueError as e:
raise InvalidURL(e, request=request)

self.cert_verify(conn, request.url, verify, cert)
url = self.request_url(request, proxies)
self.add_headers(
request,
stream=stream,
timeout=timeout,
verify=verify,
cert=cert,
proxies=proxies,
)

chunked = not (request.body is None or "Content-Length" in request.headers)

if isinstance(timeout, tuple):
try:
connect, read = timeout
timeout = TimeoutSauce(connect=connect, read=read)
except ValueError:
raise ValueError(
f"Invalid timeout {timeout}. Pass a (connect, read) timeout tuple, "
f"or a single float to set both timeouts to the same value."
)
elif isinstance(timeout, TimeoutSauce):
pass
else:
timeout = TimeoutSauce(connect=timeout, read=timeout)

try:
resp = conn.urlopen(
method=request.method,
url=url,
body=request.body,
headers=request.headers,
redirect=False,
assert_same_host=False,
preload_content=False,
decode_content=False,
retries=self.max_retries,
timeout=timeout,
chunked=chunked,
)

except (ProtocolError, OSError) as err:
raise ConnectionError(err, request=request)

except MaxRetryError as e:
if isinstance(e.reason, ConnectTimeoutError):
# TODO: Remove this in 3.0.0: see #2811
if not isinstance(e.reason, NewConnectionError):
raise ConnectTimeout(e, request=request)

if isinstance(e.reason, ResponseError):
raise RetryError(e, request=request)

if isinstance(e.reason, _ProxyError):
raise ProxyError(e, request=request)

if isinstance(e.reason, _SSLError):
# This branch is for urllib3 v1.22 and later.
raise SSLError(e, request=request)

> raise ConnectionError(e, request=request)
E requests.exceptions.ConnectionError: HTTPSConnectionPool(host='addons.allizom.org', port=443): Max retries exceeded with url: /api/v5/addons/upload/ (Caused by NameResolutionError("<urllib3.connection.HTTPSConnection object at 0x103d8c710>: Failed to resolve 'addons.allizom.org' ([Errno 8] nodename nor servname provided, or not known)"))

venv/lib/python3.11/site-packages/requests/adapters.py:597: ConnectionError
Failed tests/api_w/test_addon_uploads.py::test_upload_language_pack_unauthorized_user[Desktop] 5.06
selenium = <selenium.webdriver.firefox.webdriver.WebDriver (session="5818c8ff-5965-4b53-8053-94699e4ba3a2")>, base_url = 'https://addons.allizom.org'

@pytest.mark.serial
def test_upload_language_pack_unauthorized_user(selenium, base_url):
"""Users not part of the language pack submission group are not allowed to submit langpacks"""
# get the sessionid for a regular user
> page = Home(selenium, base_url).open().wait_for_page_to_load()

tests/api_w/test_addon_uploads.py:1103:
_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _
venv/lib/python3.11/site-packages/pypom/page.py:130: in open
self.driver_adapter.open(self.seed_url)
venv/lib/python3.11/site-packages/pypom/selenium_driver.py:44: in open
self.driver.get(url)
venv/lib/python3.11/site-packages/selenium/webdriver/remote/webdriver.py:441: in get
self.execute(Command.GET, {'url': url})
venv/lib/python3.11/site-packages/selenium/webdriver/remote/webdriver.py:429: in execute
self.error_handler.check_response(response)
_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _

self = <selenium.webdriver.remote.errorhandler.ErrorHandler object at 0x103fefc90>
response = {'status': 500, 'value': '{"value":{"error":"unknown error","message":"Reached error page: about:neterror?e=dnsNotFoun....sys.mjs:156:19\\nreceiveMessage@chrome://remote/content/marionette/actors/MarionetteEventsParent.sys.mjs:33:25\\n"}}'}

def check_response(self, response: Dict[str, Any]) -> None:
"""
Checks that a JSON response from the WebDriver does not have an error.

:Args:
- response - The JSON response from the WebDriver server as a dictionary
object.

:Raises: If the response contains an error message.
"""
status = response.get('status', None)
if not status or status == ErrorCode.SUCCESS:
return
value = None
message = response.get("message", "")
screen: str = response.get("screen", "")
stacktrace = None
if isinstance(status, int):
value_json = response.get('value', None)
if value_json and isinstance(value_json, str):
import json
try:
value = json.loads(value_json)
if len(value.keys()) == 1:
value = value['value']
status = value.get('error', None)
if not status:
status = value.get("status", ErrorCode.UNKNOWN_ERROR)
message = value.get("value") or value.get("message")
if not isinstance(message, str):
value = message
message = message.get('message')
else:
message = value.get('message', None)
except ValueError:
pass

exception_class: Type[WebDriverException]
if status in ErrorCode.NO_SUCH_ELEMENT:
exception_class = NoSuchElementException
elif status in ErrorCode.NO_SUCH_FRAME:
exception_class = NoSuchFrameException
elif status in ErrorCode.NO_SUCH_SHADOW_ROOT:
exception_class = NoSuchShadowRootException
elif status in ErrorCode.NO_SUCH_WINDOW:
exception_class = NoSuchWindowException
elif status in ErrorCode.STALE_ELEMENT_REFERENCE:
exception_class = StaleElementReferenceException
elif status in ErrorCode.ELEMENT_NOT_VISIBLE:
exception_class = ElementNotVisibleException
elif status in ErrorCode.INVALID_ELEMENT_STATE:
exception_class = InvalidElementStateException
elif status in ErrorCode.INVALID_SELECTOR \
or status in ErrorCode.INVALID_XPATH_SELECTOR \
or status in ErrorCode.INVALID_XPATH_SELECTOR_RETURN_TYPER:
exception_class = InvalidSelectorException
elif status in ErrorCode.ELEMENT_IS_NOT_SELECTABLE:
exception_class = ElementNotSelectableException
elif status in ErrorCode.ELEMENT_NOT_INTERACTABLE:
exception_class = ElementNotInteractableException
elif status in ErrorCode.INVALID_COOKIE_DOMAIN:
exception_class = InvalidCookieDomainException
elif status in ErrorCode.UNABLE_TO_SET_COOKIE:
exception_class = UnableToSetCookieException
elif status in ErrorCode.TIMEOUT:
exception_class = TimeoutException
elif status in ErrorCode.SCRIPT_TIMEOUT:
exception_class = TimeoutException
elif status in ErrorCode.UNKNOWN_ERROR:
exception_class = WebDriverException
elif status in ErrorCode.UNEXPECTED_ALERT_OPEN:
exception_class = UnexpectedAlertPresentException
elif status in ErrorCode.NO_ALERT_OPEN:
exception_class = NoAlertPresentException
elif status in ErrorCode.IME_NOT_AVAILABLE:
exception_class = ImeNotAvailableException
elif status in ErrorCode.IME_ENGINE_ACTIVATION_FAILED:
exception_class = ImeActivationFailedException
elif status in ErrorCode.MOVE_TARGET_OUT_OF_BOUNDS:
exception_class = MoveTargetOutOfBoundsException
elif status in ErrorCode.JAVASCRIPT_ERROR:
exception_class = JavascriptException
elif status in ErrorCode.SESSION_NOT_CREATED:
exception_class = SessionNotCreatedException
elif status in ErrorCode.INVALID_ARGUMENT:
exception_class = InvalidArgumentException
elif status in ErrorCode.NO_SUCH_COOKIE:
exception_class = NoSuchCookieException
elif status in ErrorCode.UNABLE_TO_CAPTURE_SCREEN:
exception_class = ScreenshotException
elif status in ErrorCode.ELEMENT_CLICK_INTERCEPTED:
exception_class = ElementClickInterceptedException
elif status in ErrorCode.INSECURE_CERTIFICATE:
exception_class = InsecureCertificateException
elif status in ErrorCode.INVALID_COORDINATES:
exception_class = InvalidCoordinatesException
elif status in ErrorCode.INVALID_SESSION_ID:
exception_class = InvalidSessionIdException
elif status in ErrorCode.UNKNOWN_METHOD:
exception_class = UnknownMethodException
else:
exception_class = WebDriverException
if not value:
value = response['value']
if isinstance(value, str):
raise exception_class(value)
if message == "" and 'message' in value:
message = value['message']

screen = None # type: ignore[assignment]
if 'screen' in value:
screen = value['screen']

stacktrace = None
st_value = value.get('stackTrace') or value.get('stacktrace')
if st_value:
if isinstance(st_value, str):
stacktrace = st_value.split('\n')
else:
stacktrace = []
try:
for frame in st_value:
line = frame.get("lineNumber", "")
file = frame.get("fileName", "<anonymous>")
if line:
file = f"{file}:{line}"
meth = frame.get('methodName', '<anonymous>')
if 'className' in frame:
meth = "{}.{}".format(frame['className'], meth)
msg = " at %s (%s)"
msg = msg % (meth, file)
stacktrace.append(msg)
except TypeError:
pass
if exception_class == UnexpectedAlertPresentException:
alert_text = None
if 'data' in value:
alert_text = value['data'].get('text')
elif 'alert' in value:
alert_text = value['alert'].get('text')
raise exception_class(message, screen, stacktrace, alert_text) # type: ignore[call-arg] # mypy is not smart enough here
> raise exception_class(message, screen, stacktrace)
E selenium.common.exceptions.WebDriverException: Message: Reached error page: about:neterror?e=dnsNotFound&u=https%3A//addons.allizom.org/&c=UTF-8&d=We%20can%E2%80%99t%20connect%20to%20the%20server%20at%20addons.allizom.org.
E Stacktrace:
E RemoteError@chrome://remote/content/shared/RemoteError.sys.mjs:8:8
E WebDriverError@chrome://remote/content/shared/webdriver/Errors.sys.mjs:202:5
E UnknownError@chrome://remote/content/shared/webdriver/Errors.sys.mjs:961:5
E checkReadyState@chrome://remote/content/marionette/navigate.sys.mjs:59:24
E onNavigation@chrome://remote/content/marionette/navigate.sys.mjs:348:39
E emit@resource://gre/modules/EventEmitter.sys.mjs:156:19
E receiveMessage@chrome://remote/content/marionette/actors/MarionetteEventsParent.sys.mjs:33:25

venv/lib/python3.11/site-packages/selenium/webdriver/remote/errorhandler.py:243: WebDriverException
Failed tests/api_w/test_addon_uploads.py::test_upload_language_pack_with_authorized_user 0.00
self = <urllib3.connection.HTTPSConnection object at 0x1036fb090>

def _new_conn(self) -> socket.socket:
"""Establish a socket connection and set nodelay settings on it.

:return: New socket connection.
"""
try:
> sock = connection.create_connection(
(self._dns_host, self.port),
self.timeout,
source_address=self.source_address,
socket_options=self.socket_options,
)

venv/lib/python3.11/site-packages/urllib3/connection.py:196:
_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _
venv/lib/python3.11/site-packages/urllib3/util/connection.py:60: in create_connection
for res in socket.getaddrinfo(host, port, family, socket.SOCK_STREAM):
_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _

host = 'addons.allizom.org', port = 443, family = <AddressFamily.AF_UNSPEC: 0>, type = <SocketKind.SOCK_STREAM: 1>, proto = 0, flags = 0

def getaddrinfo(host, port, family=0, type=0, proto=0, flags=0):
"""Resolve host and port into list of address info entries.

Translate the host/port argument into a sequence of 5-tuples that contain
all the necessary arguments for creating a socket connected to that service.
host is a domain name, a string representation of an IPv4/v6 address or
None. port is a string service name such as 'http', a numeric port number or
None. By passing None as the value of host and port, you can pass NULL to
the underlying C API.

The family, type and proto arguments can be optionally specified in order to
narrow the list of addresses returned. Passing zero as a value for each of
these arguments selects the full range of results.
"""
# We override this function since we want to translate the numeric family
# and socket type values to enum constants.
addrlist = []
> for res in _socket.getaddrinfo(host, port, family, type, proto, flags):
E socket.gaierror: [Errno 8] nodename nor servname provided, or not known

/Library/Frameworks/Python.framework/Versions/3.11/lib/python3.11/socket.py:962: gaierror

The above exception was the direct cause of the following exception:

self = <urllib3.connectionpool.HTTPSConnectionPool object at 0x1036f9010>, method = 'POST', url = '/api/v5/addons/upload/'
body = b'--4b0017d4cd9f27ec5b8166deac5dad7c\r\nContent-Disposition: form-data; name="channel"\r\n\r\nlisted\r\n--4b0017d4cd9f...x05\x06\x00\x00\x00\x00\x02\x03\x02\x03\x05\x8b\x01\x00\xf9e\n\x00\x00\x00\r\n--4b0017d4cd9f27ec5b8166deac5dad7c--\r\n'
headers = {'User-Agent': 'python-requests/2.32.0', 'Accept-Encoding': 'gzip, deflate', 'Accept': '*/*', 'Connection': 'keep-aliv...uvakt3v', 'Content-Length': '782857', 'Content-Type': 'multipart/form-data; boundary=4b0017d4cd9f27ec5b8166deac5dad7c'}
retries = Retry(total=0, connect=None, read=False, redirect=None, status=None), redirect = False, assert_same_host = False, timeout = Timeout(connect=None, read=None, total=None), pool_timeout = None
release_conn = False, chunked = False, body_pos = None, preload_content = False, decode_content = False, response_kw = {}
parsed_url = Url(scheme=None, auth=None, host=None, port=None, path='/api/v5/addons/upload/', query=None, fragment=None), destination_scheme = None, conn = None, release_this_conn = True
http_tunnel_required = False, err = None, clean_exit = False

def urlopen( # type: ignore[override]
self,
method: str,
url: str,
body: _TYPE_BODY | None = None,
headers: typing.Mapping[str, str] | None = None,
retries: Retry | bool | int | None = None,
redirect: bool = True,
assert_same_host: bool = True,
timeout: _TYPE_TIMEOUT = _DEFAULT_TIMEOUT,
pool_timeout: int | None = None,
release_conn: bool | None = None,
chunked: bool = False,
body_pos: _TYPE_BODY_POSITION | None = None,
preload_content: bool = True,
decode_content: bool = True,
**response_kw: typing.Any,
) -> BaseHTTPResponse:
"""
Get a connection from the pool and perform an HTTP request. This is the
lowest level call for making a request, so you'll need to specify all
the raw details.

.. note::

More commonly, it's appropriate to use a convenience method
such as :meth:`request`.

.. note::

`release_conn` will only behave as expected if
`preload_content=False` because we want to make
`preload_content=False` the default behaviour someday soon without
breaking backwards compatibility.

:param method:
HTTP request method (such as GET, POST, PUT, etc.)

:param url:
The URL to perform the request on.

:param body:
Data to send in the request body, either :class:`str`, :class:`bytes`,
an iterable of :class:`str`/:class:`bytes`, or a file-like object.

:param headers:
Dictionary of custom headers to send, such as User-Agent,
If-None-Match, etc. If None, pool headers are used. If provided,
these headers completely replace any pool-specific headers.

:param retries:
Configure the number of retries to allow before raising a
:class:`~urllib3.exceptions.MaxRetryError` exception.

If ``None`` (default) will retry 3 times, see ``Retry.DEFAULT``. Pass a
:class:`~urllib3.util.retry.Retry` object for fine-grained control
over different types of retries.
Pass an integer number to retry connection errors that many times,
but no other types of errors. Pass zero to never retry.

If ``False``, then retries are disabled and any exception is raised
immediately. Also, instead of raising a MaxRetryError on redirects,
the redirect response will be returned.

:type retries: :class:`~urllib3.util.retry.Retry`, False, or an int.

:param redirect:
If True, automatically handle redirects (status codes 301, 302,
303, 307, 308). Each redirect counts as a retry. Disabling retries
will disable redirect, too.

:param assert_same_host:
If ``True``, will make sure that the host of the pool requests is
consistent else will raise HostChangedError. When ``False``, you can
use the pool on an HTTP proxy and request foreign hosts.

:param timeout:
If specified, overrides the default timeout for this one
request. It may be a float (in seconds) or an instance of
:class:`urllib3.util.Timeout`.

:param pool_timeout:
If set and the pool is set to block=True, then this method will
block for ``pool_timeout`` seconds and raise EmptyPoolError if no
connection is available within the time period.

:param bool preload_content:
If True, the response's body will be preloaded into memory.

:param bool decode_content:
If True, will attempt to decode the body based on the
'content-encoding' header.

:param release_conn:
If False, then the urlopen call will not release the connection
back into the pool once a response is received (but will release if
you read the entire contents of the response such as when
`preload_content=True`). This is useful if you're not preloading
the response's content immediately. You will need to call
``r.release_conn()`` on the response ``r`` to return the connection
back into the pool. If None, it takes the value of ``preload_content``
which defaults to ``True``.

:param bool chunked:
If True, urllib3 will send the body using chunked transfer
encoding. Otherwise, urllib3 will send the body using the standard
content-length form. Defaults to False.

:param int body_pos:
Position to seek to in file-like body in the event of a retry or
redirect. Typically this won't need to be set because urllib3 will
auto-populate the value when needed.
"""
parsed_url = parse_url(url)
destination_scheme = parsed_url.scheme

if headers is None:
headers = self.headers

if not isinstance(retries, Retry):
retries = Retry.from_int(retries, redirect=redirect, default=self.retries)

if release_conn is None:
release_conn = preload_content

# Check host
if assert_same_host and not self.is_same_host(url):
raise HostChangedError(self, url, retries)

# Ensure that the URL we're connecting to is properly encoded
if url.startswith("/"):
url = to_str(_encode_target(url))
else:
url = to_str(parsed_url.url)

conn = None

# Track whether `conn` needs to be released before
# returning/raising/recursing. Update this variable if necessary, and
# leave `release_conn` constant throughout the function. That way, if
# the function recurses, the original value of `release_conn` will be
# passed down into the recursive call, and its value will be respected.
#
# See issue #651 [1] for details.
#
# [1] <https://github.com/urllib3/urllib3/issues/651>
release_this_conn = release_conn

http_tunnel_required = connection_requires_http_tunnel(
self.proxy, self.proxy_config, destination_scheme
)

# Merge the proxy headers. Only done when not using HTTP CONNECT. We
# have to copy the headers dict so we can safely change it without those
# changes being reflected in anyone else's copy.
if not http_tunnel_required:
headers = headers.copy() # type: ignore[attr-defined]
headers.update(self.proxy_headers) # type: ignore[union-attr]

# Must keep the exception bound to a separate variable or else Python 3
# complains about UnboundLocalError.
err = None

# Keep track of whether we cleanly exited the except block. This
# ensures we do proper cleanup in finally.
clean_exit = False

# Rewind body position, if needed. Record current position
# for future rewinds in the event of a redirect/retry.
body_pos = set_file_position(body, body_pos)

try:
# Request a connection from the queue.
timeout_obj = self._get_timeout(timeout)
conn = self._get_conn(timeout=pool_timeout)

conn.timeout = timeout_obj.connect_timeout # type: ignore[assignment]

# Is this a closed/new connection that requires CONNECT tunnelling?
if self.proxy is not None and http_tunnel_required and conn.is_closed:
try:
self._prepare_proxy(conn)
except (BaseSSLError, OSError, SocketTimeout) as e:
self._raise_timeout(
err=e, url=self.proxy.url, timeout_value=conn.timeout
)
raise

# If we're going to release the connection in ``finally:``, then
# the response doesn't need to know about the connection. Otherwise
# it will also try to release it and we'll have a double-release
# mess.
response_conn = conn if not release_conn else None

# Make the request on the HTTPConnection object
> response = self._make_request(
conn,
method,
url,
timeout=timeout_obj,
body=body,
headers=headers,
chunked=chunked,
retries=retries,
response_conn=response_conn,
preload_content=preload_content,
decode_content=decode_content,
**response_kw,
)

venv/lib/python3.11/site-packages/urllib3/connectionpool.py:789:
_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _
venv/lib/python3.11/site-packages/urllib3/connectionpool.py:490: in _make_request
raise new_e
venv/lib/python3.11/site-packages/urllib3/connectionpool.py:466: in _make_request
self._validate_conn(conn)
venv/lib/python3.11/site-packages/urllib3/connectionpool.py:1095: in _validate_conn
conn.connect()
venv/lib/python3.11/site-packages/urllib3/connection.py:615: in connect
self.sock = sock = self._new_conn()
_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _

self = <urllib3.connection.HTTPSConnection object at 0x1036fb090>

def _new_conn(self) -> socket.socket:
"""Establish a socket connection and set nodelay settings on it.

:return: New socket connection.
"""
try:
sock = connection.create_connection(
(self._dns_host, self.port),
self.timeout,
source_address=self.source_address,
socket_options=self.socket_options,
)
except socket.gaierror as e:
> raise NameResolutionError(self.host, self, e) from e
E urllib3.exceptions.NameResolutionError: <urllib3.connection.HTTPSConnection object at 0x1036fb090>: Failed to resolve 'addons.allizom.org' ([Errno 8] nodename nor servname provided, or not known)

venv/lib/python3.11/site-packages/urllib3/connection.py:203: NameResolutionError

The above exception was the direct cause of the following exception:

self = <requests.adapters.HTTPAdapter object at 0x103de7550>, request = <PreparedRequest [POST]>, stream = False, timeout = Timeout(connect=None, read=None, total=None), verify = True, cert = None
proxies = OrderedDict()

def send(
self, request, stream=False, timeout=None, verify=True, cert=None, proxies=None
):
"""Sends PreparedRequest object. Returns Response object.

:param request: The :class:`PreparedRequest <PreparedRequest>` being sent.
:param stream: (optional) Whether to stream the request content.
:param timeout: (optional) How long to wait for the server to send
data before giving up, as a float, or a :ref:`(connect timeout,
read timeout) <timeouts>` tuple.
:type timeout: float or tuple or urllib3 Timeout object
:param verify: (optional) Either a boolean, in which case it controls whether
we verify the server's TLS certificate, or a string, in which case it
must be a path to a CA bundle to use
:param cert: (optional) Any user-provided SSL certificate to be trusted.
:param proxies: (optional) The proxies dictionary to apply to the request.
:rtype: requests.Response
"""

try:
conn = self._get_connection(request, verify, proxies=proxies, cert=cert)
except LocationValueError as e:
raise InvalidURL(e, request=request)

self.cert_verify(conn, request.url, verify, cert)
url = self.request_url(request, proxies)
self.add_headers(
request,
stream=stream,
timeout=timeout,
verify=verify,
cert=cert,
proxies=proxies,
)

chunked = not (request.body is None or "Content-Length" in request.headers)

if isinstance(timeout, tuple):
try:
connect, read = timeout
timeout = TimeoutSauce(connect=connect, read=read)
except ValueError:
raise ValueError(
f"Invalid timeout {timeout}. Pass a (connect, read) timeout tuple, "
f"or a single float to set both timeouts to the same value."
)
elif isinstance(timeout, TimeoutSauce):
pass
else:
timeout = TimeoutSauce(connect=timeout, read=timeout)

try:
> resp = conn.urlopen(
method=request.method,
url=url,
body=request.body,
headers=request.headers,
redirect=False,
assert_same_host=False,
preload_content=False,
decode_content=False,
retries=self.max_retries,
timeout=timeout,
chunked=chunked,
)

venv/lib/python3.11/site-packages/requests/adapters.py:564:
_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _
venv/lib/python3.11/site-packages/urllib3/connectionpool.py:843: in urlopen
retries = retries.increment(
_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _

self = Retry(total=0, connect=None, read=False, redirect=None, status=None), method = 'POST', url = '/api/v5/addons/upload/', response = None
error = NameResolutionError("<urllib3.connection.HTTPSConnection object at 0x1036fb090>: Failed to resolve 'addons.allizom.org' ([Errno 8] nodename nor servname provided, or not known)")
_pool = <urllib3.connectionpool.HTTPSConnectionPool object at 0x1036f9010>, _stacktrace = <traceback object at 0x1036fb9c0>

def increment(
self,
method: str | None = None,
url: str | None = None,
response: BaseHTTPResponse | None = None,
error: Exception | None = None,
_pool: ConnectionPool | None = None,
_stacktrace: TracebackType | None = None,
) -> Self:
"""Return a new Retry object with incremented retry counters.

:param response: A response object, or None, if the server did not
return a response.
:type response: :class:`~urllib3.response.BaseHTTPResponse`
:param Exception error: An error encountered during the request, or
None if the response was received successfully.

:return: A new ``Retry`` object.
"""
if self.total is False and error:
# Disabled, indicate to re-raise the error.
raise reraise(type(error), error, _stacktrace)

total = self.total
if total is not None:
total -= 1

connect = self.connect
read = self.read
redirect = self.redirect
status_count = self.status
other = self.other
cause = "unknown"
status = None
redirect_location = None

if error and self._is_connection_error(error):
# Connect retry?
if connect is False:
raise reraise(type(error), error, _stacktrace)
elif connect is not None:
connect -= 1

elif error and self._is_read_error(error):
# Read retry?
if read is False or method is None or not self._is_method_retryable(method):
raise reraise(type(error), error, _stacktrace)
elif read is not None:
read -= 1

elif error:
# Other retry?
if other is not None:
other -= 1

elif response and response.get_redirect_location():
# Redirect retry?
if redirect is not None:
redirect -= 1
cause = "too many redirects"
response_redirect_location = response.get_redirect_location()
if response_redirect_location:
redirect_location = response_redirect_location
status = response.status

else:
# Incrementing because of a server error like a 500 in
# status_forcelist and the given method is in the allowed_methods
cause = ResponseError.GENERIC_ERROR
if response and response.status:
if status_count is not None:
status_count -= 1
cause = ResponseError.SPECIFIC_ERROR.format(status_code=response.status)
status = response.status

history = self.history + (
RequestHistory(method, url, error, status, redirect_location),
)

new_retry = self.new(
total=total,
connect=connect,
read=read,
redirect=redirect,
status=status_count,
other=other,
history=history,
)

if new_retry.is_exhausted():
reason = error or ResponseError(cause)
> raise MaxRetryError(_pool, url, reason) from reason # type: ignore[arg-type]
E urllib3.exceptions.MaxRetryError: HTTPSConnectionPool(host='addons.allizom.org', port=443): Max retries exceeded with url: /api/v5/addons/upload/ (Caused by NameResolutionError("<urllib3.connection.HTTPSConnection object at 0x1036fb090>: Failed to resolve 'addons.allizom.org' ([Errno 8] nodename nor servname provided, or not known)"))

venv/lib/python3.11/site-packages/urllib3/util/retry.py:519: MaxRetryError

During handling of the above exception, another exception occurred:

base_url = 'https://addons.allizom.org', session_auth = 'ldvd5ag27bkfpukx6rn2lcj0yuvakt3v'

@pytest.mark.serial
@pytest.mark.create_session("api_user")
def test_upload_language_pack_with_authorized_user(base_url, session_auth):
"""Upload a langpack with a user that belongs to the language pack submissions group"""
with open("sample-addons/lang-pack.xpi", "rb") as file:
> upload = requests.post(
url=f"{base_url}{_upload}",
headers={"Authorization": f"Session {session_auth}"},
files={"upload": file},
data={"channel": "listed"},
)

tests/api_w/test_addon_uploads.py:1139:
_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _
venv/lib/python3.11/site-packages/requests/api.py:115: in post
return request("post", url, data=data, json=json, **kwargs)
venv/lib/python3.11/site-packages/requests/api.py:59: in request
return session.request(method=method, url=url, **kwargs)
venv/lib/python3.11/site-packages/requests/sessions.py:589: in request
resp = self.send(prep, **send_kwargs)
venv/lib/python3.11/site-packages/requests/sessions.py:703: in send
r = adapter.send(request, **kwargs)
_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _

self = <requests.adapters.HTTPAdapter object at 0x103de7550>, request = <PreparedRequest [POST]>, stream = False, timeout = Timeout(connect=None, read=None, total=None), verify = True, cert = None
proxies = OrderedDict()

def send(
self, request, stream=False, timeout=None, verify=True, cert=None, proxies=None
):
"""Sends PreparedRequest object. Returns Response object.

:param request: The :class:`PreparedRequest <PreparedRequest>` being sent.
:param stream: (optional) Whether to stream the request content.
:param timeout: (optional) How long to wait for the server to send
data before giving up, as a float, or a :ref:`(connect timeout,
read timeout) <timeouts>` tuple.
:type timeout: float or tuple or urllib3 Timeout object
:param verify: (optional) Either a boolean, in which case it controls whether
we verify the server's TLS certificate, or a string, in which case it
must be a path to a CA bundle to use
:param cert: (optional) Any user-provided SSL certificate to be trusted.
:param proxies: (optional) The proxies dictionary to apply to the request.
:rtype: requests.Response
"""

try:
conn = self._get_connection(request, verify, proxies=proxies, cert=cert)
except LocationValueError as e:
raise InvalidURL(e, request=request)

self.cert_verify(conn, request.url, verify, cert)
url = self.request_url(request, proxies)
self.add_headers(
request,
stream=stream,
timeout=timeout,
verify=verify,
cert=cert,
proxies=proxies,
)

chunked = not (request.body is None or "Content-Length" in request.headers)

if isinstance(timeout, tuple):
try:
connect, read = timeout
timeout = TimeoutSauce(connect=connect, read=read)
except ValueError:
raise ValueError(
f"Invalid timeout {timeout}. Pass a (connect, read) timeout tuple, "
f"or a single float to set both timeouts to the same value."
)
elif isinstance(timeout, TimeoutSauce):
pass
else:
timeout = TimeoutSauce(connect=timeout, read=timeout)

try:
resp = conn.urlopen(
method=request.method,
url=url,
body=request.body,
headers=request.headers,
redirect=False,
assert_same_host=False,
preload_content=False,
decode_content=False,
retries=self.max_retries,
timeout=timeout,
chunked=chunked,
)

except (ProtocolError, OSError) as err:
raise ConnectionError(err, request=request)

except MaxRetryError as e:
if isinstance(e.reason, ConnectTimeoutError):
# TODO: Remove this in 3.0.0: see #2811
if not isinstance(e.reason, NewConnectionError):
raise ConnectTimeout(e, request=request)

if isinstance(e.reason, ResponseError):
raise RetryError(e, request=request)

if isinstance(e.reason, _ProxyError):
raise ProxyError(e, request=request)

if isinstance(e.reason, _SSLError):
# This branch is for urllib3 v1.22 and later.
raise SSLError(e, request=request)

> raise ConnectionError(e, request=request)
E requests.exceptions.ConnectionError: HTTPSConnectionPool(host='addons.allizom.org', port=443): Max retries exceeded with url: /api/v5/addons/upload/ (Caused by NameResolutionError("<urllib3.connection.HTTPSConnection object at 0x1036fb090>: Failed to resolve 'addons.allizom.org' ([Errno 8] nodename nor servname provided, or not known)"))

venv/lib/python3.11/site-packages/requests/adapters.py:597: ConnectionError
Failed tests/api_w/test_addon_uploads.py::test_upload_language_pack_incorrect_category 0.00
self = <urllib3.connection.HTTPSConnection object at 0x103bc8d50>

def _new_conn(self) -> socket.socket:
"""Establish a socket connection and set nodelay settings on it.

:return: New socket connection.
"""
try:
> sock = connection.create_connection(
(self._dns_host, self.port),
self.timeout,
source_address=self.source_address,
socket_options=self.socket_options,
)

venv/lib/python3.11/site-packages/urllib3/connection.py:196:
_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _
venv/lib/python3.11/site-packages/urllib3/util/connection.py:60: in create_connection
for res in socket.getaddrinfo(host, port, family, socket.SOCK_STREAM):
_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _

host = 'addons.allizom.org', port = 443, family = <AddressFamily.AF_UNSPEC: 0>, type = <SocketKind.SOCK_STREAM: 1>, proto = 0, flags = 0

def getaddrinfo(host, port, family=0, type=0, proto=0, flags=0):
"""Resolve host and port into list of address info entries.

Translate the host/port argument into a sequence of 5-tuples that contain
all the necessary arguments for creating a socket connected to that service.
host is a domain name, a string representation of an IPv4/v6 address or
None. port is a string service name such as 'http', a numeric port number or
None. By passing None as the value of host and port, you can pass NULL to
the underlying C API.

The family, type and proto arguments can be optionally specified in order to
narrow the list of addresses returned. Passing zero as a value for each of
these arguments selects the full range of results.
"""
# We override this function since we want to translate the numeric family
# and socket type values to enum constants.
addrlist = []
> for res in _socket.getaddrinfo(host, port, family, type, proto, flags):
E socket.gaierror: [Errno 8] nodename nor servname provided, or not known

/Library/Frameworks/Python.framework/Versions/3.11/lib/python3.11/socket.py:962: gaierror

The above exception was the direct cause of the following exception:

self = <urllib3.connectionpool.HTTPSConnectionPool object at 0x103bc8a90>, method = 'POST', url = '/api/v5/addons/upload/'
body = b'--dca31a4e0ccfd0c0db4bb572206c60b3\r\nContent-Disposition: form-data; name="channel"\r\n\r\nlisted\r\n--dca31a4e0ccf...x05\x06\x00\x00\x00\x00\x02\x03\x02\x03\x05\x8b\x01\x00\xf9e\n\x00\x00\x00\r\n--dca31a4e0ccfd0c0db4bb572206c60b3--\r\n'
headers = {'User-Agent': 'python-requests/2.32.0', 'Accept-Encoding': 'gzip, deflate', 'Accept': '*/*', 'Connection': 'keep-aliv...uvakt3v', 'Content-Length': '782857', 'Content-Type': 'multipart/form-data; boundary=dca31a4e0ccfd0c0db4bb572206c60b3'}
retries = Retry(total=0, connect=None, read=False, redirect=None, status=None), redirect = False, assert_same_host = False, timeout = Timeout(connect=None, read=None, total=None), pool_timeout = None
release_conn = False, chunked = False, body_pos = None, preload_content = False, decode_content = False, response_kw = {}
parsed_url = Url(scheme=None, auth=None, host=None, port=None, path='/api/v5/addons/upload/', query=None, fragment=None), destination_scheme = None, conn = None, release_this_conn = True
http_tunnel_required = False, err = None, clean_exit = False

def urlopen( # type: ignore[override]
self,
method: str,
url: str,
body: _TYPE_BODY | None = None,
headers: typing.Mapping[str, str] | None = None,
retries: Retry | bool | int | None = None,
redirect: bool = True,
assert_same_host: bool = True,
timeout: _TYPE_TIMEOUT = _DEFAULT_TIMEOUT,
pool_timeout: int | None = None,
release_conn: bool | None = None,
chunked: bool = False,
body_pos: _TYPE_BODY_POSITION | None = None,
preload_content: bool = True,
decode_content: bool = True,
**response_kw: typing.Any,
) -> BaseHTTPResponse:
"""
Get a connection from the pool and perform an HTTP request. This is the
lowest level call for making a request, so you'll need to specify all
the raw details.

.. note::

More commonly, it's appropriate to use a convenience method
such as :meth:`request`.

.. note::

`release_conn` will only behave as expected if
`preload_content=False` because we want to make
`preload_content=False` the default behaviour someday soon without
breaking backwards compatibility.

:param method:
HTTP request method (such as GET, POST, PUT, etc.)

:param url:
The URL to perform the request on.

:param body:
Data to send in the request body, either :class:`str`, :class:`bytes`,
an iterable of :class:`str`/:class:`bytes`, or a file-like object.

:param headers:
Dictionary of custom headers to send, such as User-Agent,
If-None-Match, etc. If None, pool headers are used. If provided,
these headers completely replace any pool-specific headers.

:param retries:
Configure the number of retries to allow before raising a
:class:`~urllib3.exceptions.MaxRetryError` exception.

If ``None`` (default) will retry 3 times, see ``Retry.DEFAULT``. Pass a
:class:`~urllib3.util.retry.Retry` object for fine-grained control
over different types of retries.
Pass an integer number to retry connection errors that many times,
but no other types of errors. Pass zero to never retry.

If ``False``, then retries are disabled and any exception is raised
immediately. Also, instead of raising a MaxRetryError on redirects,
the redirect response will be returned.

:type retries: :class:`~urllib3.util.retry.Retry`, False, or an int.

:param redirect:
If True, automatically handle redirects (status codes 301, 302,
303, 307, 308). Each redirect counts as a retry. Disabling retries
will disable redirect, too.

:param assert_same_host:
If ``True``, will make sure that the host of the pool requests is
consistent else will raise HostChangedError. When ``False``, you can
use the pool on an HTTP proxy and request foreign hosts.

:param timeout:
If specified, overrides the default timeout for this one
request. It may be a float (in seconds) or an instance of
:class:`urllib3.util.Timeout`.

:param pool_timeout:
If set and the pool is set to block=True, then this method will
block for ``pool_timeout`` seconds and raise EmptyPoolError if no
connection is available within the time period.

:param bool preload_content:
If True, the response's body will be preloaded into memory.

:param bool decode_content:
If True, will attempt to decode the body based on the
'content-encoding' header.

:param release_conn:
If False, then the urlopen call will not release the connection
back into the pool once a response is received (but will release if
you read the entire contents of the response such as when
`preload_content=True`). This is useful if you're not preloading
the response's content immediately. You will need to call
``r.release_conn()`` on the response ``r`` to return the connection
back into the pool. If None, it takes the value of ``preload_content``
which defaults to ``True``.

:param bool chunked:
If True, urllib3 will send the body using chunked transfer
encoding. Otherwise, urllib3 will send the body using the standard
content-length form. Defaults to False.

:param int body_pos:
Position to seek to in file-like body in the event of a retry or
redirect. Typically this won't need to be set because urllib3 will
auto-populate the value when needed.
"""
parsed_url = parse_url(url)
destination_scheme = parsed_url.scheme

if headers is None:
headers = self.headers

if not isinstance(retries, Retry):
retries = Retry.from_int(retries, redirect=redirect, default=self.retries)

if release_conn is None:
release_conn = preload_content

# Check host
if assert_same_host and not self.is_same_host(url):
raise HostChangedError(self, url, retries)

# Ensure that the URL we're connecting to is properly encoded
if url.startswith("/"):
url = to_str(_encode_target(url))
else:
url = to_str(parsed_url.url)

conn = None

# Track whether `conn` needs to be released before
# returning/raising/recursing. Update this variable if necessary, and
# leave `release_conn` constant throughout the function. That way, if
# the function recurses, the original value of `release_conn` will be
# passed down into the recursive call, and its value will be respected.
#
# See issue #651 [1] for details.
#
# [1] <https://github.com/urllib3/urllib3/issues/651>
release_this_conn = release_conn

http_tunnel_required = connection_requires_http_tunnel(
self.proxy, self.proxy_config, destination_scheme
)

# Merge the proxy headers. Only done when not using HTTP CONNECT. We
# have to copy the headers dict so we can safely change it without those
# changes being reflected in anyone else's copy.
if not http_tunnel_required:
headers = headers.copy() # type: ignore[attr-defined]
headers.update(self.proxy_headers) # type: ignore[union-attr]

# Must keep the exception bound to a separate variable or else Python 3
# complains about UnboundLocalError.
err = None

# Keep track of whether we cleanly exited the except block. This
# ensures we do proper cleanup in finally.
clean_exit = False

# Rewind body position, if needed. Record current position
# for future rewinds in the event of a redirect/retry.
body_pos = set_file_position(body, body_pos)

try:
# Request a connection from the queue.
timeout_obj = self._get_timeout(timeout)
conn = self._get_conn(timeout=pool_timeout)

conn.timeout = timeout_obj.connect_timeout # type: ignore[assignment]

# Is this a closed/new connection that requires CONNECT tunnelling?
if self.proxy is not None and http_tunnel_required and conn.is_closed:
try:
self._prepare_proxy(conn)
except (BaseSSLError, OSError, SocketTimeout) as e:
self._raise_timeout(
err=e, url=self.proxy.url, timeout_value=conn.timeout
)
raise

# If we're going to release the connection in ``finally:``, then
# the response doesn't need to know about the connection. Otherwise
# it will also try to release it and we'll have a double-release
# mess.
response_conn = conn if not release_conn else None

# Make the request on the HTTPConnection object
> response = self._make_request(
conn,
method,
url,
timeout=timeout_obj,
body=body,
headers=headers,
chunked=chunked,
retries=retries,
response_conn=response_conn,
preload_content=preload_content,
decode_content=decode_content,
**response_kw,
)

venv/lib/python3.11/site-packages/urllib3/connectionpool.py:789:
_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _
venv/lib/python3.11/site-packages/urllib3/connectionpool.py:490: in _make_request
raise new_e
venv/lib/python3.11/site-packages/urllib3/connectionpool.py:466: in _make_request
self._validate_conn(conn)
venv/lib/python3.11/site-packages/urllib3/connectionpool.py:1095: in _validate_conn
conn.connect()
venv/lib/python3.11/site-packages/urllib3/connection.py:615: in connect
self.sock = sock = self._new_conn()
_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _

self = <urllib3.connection.HTTPSConnection object at 0x103bc8d50>

def _new_conn(self) -> socket.socket:
"""Establish a socket connection and set nodelay settings on it.

:return: New socket connection.
"""
try:
sock = connection.create_connection(
(self._dns_host, self.port),
self.timeout,
source_address=self.source_address,
socket_options=self.socket_options,
)
except socket.gaierror as e:
> raise NameResolutionError(self.host, self, e) from e
E urllib3.exceptions.NameResolutionError: <urllib3.connection.HTTPSConnection object at 0x103bc8d50>: Failed to resolve 'addons.allizom.org' ([Errno 8] nodename nor servname provided, or not known)

venv/lib/python3.11/site-packages/urllib3/connection.py:203: NameResolutionError

The above exception was the direct cause of the following exception:

self = <requests.adapters.HTTPAdapter object at 0x103bca890>, request = <PreparedRequest [POST]>, stream = False, timeout = Timeout(connect=None, read=None, total=None), verify = True, cert = None
proxies = OrderedDict()

def send(
self, request, stream=False, timeout=None, verify=True, cert=None, proxies=None
):
"""Sends PreparedRequest object. Returns Response object.

:param request: The :class:`PreparedRequest <PreparedRequest>` being sent.
:param stream: (optional) Whether to stream the request content.
:param timeout: (optional) How long to wait for the server to send
data before giving up, as a float, or a :ref:`(connect timeout,
read timeout) <timeouts>` tuple.
:type timeout: float or tuple or urllib3 Timeout object
:param verify: (optional) Either a boolean, in which case it controls whether
we verify the server's TLS certificate, or a string, in which case it
must be a path to a CA bundle to use
:param cert: (optional) Any user-provided SSL certificate to be trusted.
:param proxies: (optional) The proxies dictionary to apply to the request.
:rtype: requests.Response
"""

try:
conn = self._get_connection(request, verify, proxies=proxies, cert=cert)
except LocationValueError as e:
raise InvalidURL(e, request=request)

self.cert_verify(conn, request.url, verify, cert)
url = self.request_url(request, proxies)
self.add_headers(
request,
stream=stream,
timeout=timeout,
verify=verify,
cert=cert,
proxies=proxies,
)

chunked = not (request.body is None or "Content-Length" in request.headers)

if isinstance(timeout, tuple):
try:
connect, read = timeout
timeout = TimeoutSauce(connect=connect, read=read)
except ValueError:
raise ValueError(
f"Invalid timeout {timeout}. Pass a (connect, read) timeout tuple, "
f"or a single float to set both timeouts to the same value."
)
elif isinstance(timeout, TimeoutSauce):
pass
else:
timeout = TimeoutSauce(connect=timeout, read=timeout)

try:
> resp = conn.urlopen(
method=request.method,
url=url,
body=request.body,
headers=request.headers,
redirect=False,
assert_same_host=False,
preload_content=False,
decode_content=False,
retries=self.max_retries,
timeout=timeout,
chunked=chunked,
)

venv/lib/python3.11/site-packages/requests/adapters.py:564:
_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _
venv/lib/python3.11/site-packages/urllib3/connectionpool.py:843: in urlopen
retries = retries.increment(
_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _

self = Retry(total=0, connect=None, read=False, redirect=None, status=None), method = 'POST', url = '/api/v5/addons/upload/', response = None
error = NameResolutionError("<urllib3.connection.HTTPSConnection object at 0x103bc8d50>: Failed to resolve 'addons.allizom.org' ([Errno 8] nodename nor servname provided, or not known)")
_pool = <urllib3.connectionpool.HTTPSConnectionPool object at 0x103bc8a90>, _stacktrace = <traceback object at 0x103bc9a40>

def increment(
self,
method: str | None = None,
url: str | None = None,
response: BaseHTTPResponse | None = None,
error: Exception | None = None,
_pool: ConnectionPool | None = None,
_stacktrace: TracebackType | None = None,
) -> Self:
"""Return a new Retry object with incremented retry counters.

:param response: A response object, or None, if the server did not
return a response.
:type response: :class:`~urllib3.response.BaseHTTPResponse`
:param Exception error: An error encountered during the request, or
None if the response was received successfully.

:return: A new ``Retry`` object.
"""
if self.total is False and error:
# Disabled, indicate to re-raise the error.
raise reraise(type(error), error, _stacktrace)

total = self.total
if total is not None:
total -= 1

connect = self.connect
read = self.read
redirect = self.redirect
status_count = self.status
other = self.other
cause = "unknown"
status = None
redirect_location = None

if error and self._is_connection_error(error):
# Connect retry?
if connect is False:
raise reraise(type(error), error, _stacktrace)
elif connect is not None:
connect -= 1

elif error and self._is_read_error(error):
# Read retry?
if read is False or method is None or not self._is_method_retryable(method):
raise reraise(type(error), error, _stacktrace)
elif read is not None:
read -= 1

elif error:
# Other retry?
if other is not None:
other -= 1

elif response and response.get_redirect_location():
# Redirect retry?
if redirect is not None:
redirect -= 1
cause = "too many redirects"
response_redirect_location = response.get_redirect_location()
if response_redirect_location:
redirect_location = response_redirect_location
status = response.status

else:
# Incrementing because of a server error like a 500 in
# status_forcelist and the given method is in the allowed_methods
cause = ResponseError.GENERIC_ERROR
if response and response.status:
if status_count is not None:
status_count -= 1
cause = ResponseError.SPECIFIC_ERROR.format(status_code=response.status)
status = response.status

history = self.history + (
RequestHistory(method, url, error, status, redirect_location),
)

new_retry = self.new(
total=total,
connect=connect,
read=read,
redirect=redirect,
status=status_count,
other=other,
history=history,
)

if new_retry.is_exhausted():
reason = error or ResponseError(cause)
> raise MaxRetryError(_pool, url, reason) from reason # type: ignore[arg-type]
E urllib3.exceptions.MaxRetryError: HTTPSConnectionPool(host='addons.allizom.org', port=443): Max retries exceeded with url: /api/v5/addons/upload/ (Caused by NameResolutionError("<urllib3.connection.HTTPSConnection object at 0x103bc8d50>: Failed to resolve 'addons.allizom.org' ([Errno 8] nodename nor servname provided, or not known)"))

venv/lib/python3.11/site-packages/urllib3/util/retry.py:519: MaxRetryError

During handling of the above exception, another exception occurred:

base_url = 'https://addons.allizom.org', session_auth = 'ldvd5ag27bkfpukx6rn2lcj0yuvakt3v'

@pytest.mark.serial
@pytest.mark.create_session("api_user")
def test_upload_language_pack_incorrect_category(base_url, session_auth):
"""Language packs only accept 'general' as a category value; other values should fail"""
with open("sample-addons/lang-pack.xpi", "rb") as file:
> upload = requests.post(
url=f"{base_url}{_upload}",
headers={"Authorization": f"Session {session_auth}"},
files={"upload": file},
data={"channel": "listed"},
)

tests/api_w/test_addon_uploads.py:1171:
_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _
venv/lib/python3.11/site-packages/requests/api.py:115: in post
return request("post", url, data=data, json=json, **kwargs)
venv/lib/python3.11/site-packages/requests/api.py:59: in request
return session.request(method=method, url=url, **kwargs)
venv/lib/python3.11/site-packages/requests/sessions.py:589: in request
resp = self.send(prep, **send_kwargs)
venv/lib/python3.11/site-packages/requests/sessions.py:703: in send
r = adapter.send(request, **kwargs)
_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _

self = <requests.adapters.HTTPAdapter object at 0x103bca890>, request = <PreparedRequest [POST]>, stream = False, timeout = Timeout(connect=None, read=None, total=None), verify = True, cert = None
proxies = OrderedDict()

def send(
self, request, stream=False, timeout=None, verify=True, cert=None, proxies=None
):
"""Sends PreparedRequest object. Returns Response object.

:param request: The :class:`PreparedRequest <PreparedRequest>` being sent.
:param stream: (optional) Whether to stream the request content.
:param timeout: (optional) How long to wait for the server to send
data before giving up, as a float, or a :ref:`(connect timeout,
read timeout) <timeouts>` tuple.
:type timeout: float or tuple or urllib3 Timeout object
:param verify: (optional) Either a boolean, in which case it controls whether
we verify the server's TLS certificate, or a string, in which case it
must be a path to a CA bundle to use
:param cert: (optional) Any user-provided SSL certificate to be trusted.
:param proxies: (optional) The proxies dictionary to apply to the request.
:rtype: requests.Response
"""

try:
conn = self._get_connection(request, verify, proxies=proxies, cert=cert)
except LocationValueError as e:
raise InvalidURL(e, request=request)

self.cert_verify(conn, request.url, verify, cert)
url = self.request_url(request, proxies)
self.add_headers(
request,
stream=stream,
timeout=timeout,
verify=verify,
cert=cert,
proxies=proxies,
)

chunked = not (request.body is None or "Content-Length" in request.headers)

if isinstance(timeout, tuple):
try:
connect, read = timeout
timeout = TimeoutSauce(connect=connect, read=read)
except ValueError:
raise ValueError(
f"Invalid timeout {timeout}. Pass a (connect, read) timeout tuple, "
f"or a single float to set both timeouts to the same value."
)
elif isinstance(timeout, TimeoutSauce):
pass
else:
timeout = TimeoutSauce(connect=timeout, read=timeout)

try:
resp = conn.urlopen(
method=request.method,
url=url,
body=request.body,
headers=request.headers,
redirect=False,
assert_same_host=False,
preload_content=False,
decode_content=False,
retries=self.max_retries,
timeout=timeout,
chunked=chunked,
)

except (ProtocolError, OSError) as err:
raise ConnectionError(err, request=request)

except MaxRetryError as e:
if isinstance(e.reason, ConnectTimeoutError):
# TODO: Remove this in 3.0.0: see #2811
if not isinstance(e.reason, NewConnectionError):
raise ConnectTimeout(e, request=request)

if isinstance(e.reason, ResponseError):
raise RetryError(e, request=request)

if isinstance(e.reason, _ProxyError):
raise ProxyError(e, request=request)

if isinstance(e.reason, _SSLError):
# This branch is for urllib3 v1.22 and later.
raise SSLError(e, request=request)

> raise ConnectionError(e, request=request)
E requests.exceptions.ConnectionError: HTTPSConnectionPool(host='addons.allizom.org', port=443): Max retries exceeded with url: /api/v5/addons/upload/ (Caused by NameResolutionError("<urllib3.connection.HTTPSConnection object at 0x103bc8d50>: Failed to resolve 'addons.allizom.org' ([Errno 8] nodename nor servname provided, or not known)"))

venv/lib/python3.11/site-packages/requests/adapters.py:597: ConnectionError
Failed tests/api_w/test_addon_uploads.py::test_upload_privileged_addon_with_unauthorized_account 0.00
self = <urllib3.connection.HTTPSConnection object at 0x1040cec90>

def _new_conn(self) -> socket.socket:
"""Establish a socket connection and set nodelay settings on it.

:return: New socket connection.
"""
try:
> sock = connection.create_connection(
(self._dns_host, self.port),
self.timeout,
source_address=self.source_address,
socket_options=self.socket_options,
)

venv/lib/python3.11/site-packages/urllib3/connection.py:196:
_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _
venv/lib/python3.11/site-packages/urllib3/util/connection.py:60: in create_connection
for res in socket.getaddrinfo(host, port, family, socket.SOCK_STREAM):
_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _

host = 'addons.allizom.org', port = 443, family = <AddressFamily.AF_UNSPEC: 0>, type = <SocketKind.SOCK_STREAM: 1>, proto = 0, flags = 0

def getaddrinfo(host, port, family=0, type=0, proto=0, flags=0):
"""Resolve host and port into list of address info entries.

Translate the host/port argument into a sequence of 5-tuples that contain
all the necessary arguments for creating a socket connected to that service.
host is a domain name, a string representation of an IPv4/v6 address or
None. port is a string service name such as 'http', a numeric port number or
None. By passing None as the value of host and port, you can pass NULL to
the underlying C API.

The family, type and proto arguments can be optionally specified in order to
narrow the list of addresses returned. Passing zero as a value for each of
these arguments selects the full range of results.
"""
# We override this function since we want to translate the numeric family
# and socket type values to enum constants.
addrlist = []
> for res in _socket.getaddrinfo(host, port, family, type, proto, flags):
E socket.gaierror: [Errno 8] nodename nor servname provided, or not known

/Library/Frameworks/Python.framework/Versions/3.11/lib/python3.11/socket.py:962: gaierror

The above exception was the direct cause of the following exception:

self = <urllib3.connectionpool.HTTPSConnectionPool object at 0x1040cc510>, method = 'POST', url = '/api/v5/addons/upload/'
body = b'--fdef6c7d2e08eb882ed011200b3e56b5\r\nContent-Disposition: form-data; name="channel"\r\n\r\nunlisted\r\n--fdef6c7d2e...06\x00\x00\x00\x00\x07\x00\x07\x00\xa3\x02\x00\x00\xa6\x10\x00\x00\x00\x00\r\n--fdef6c7d2e08eb882ed011200b3e56b5--\r\n'
headers = {'User-Agent': 'python-requests/2.32.0', 'Accept-Encoding': 'gzip, deflate', 'Accept': '*/*', 'Connection': 'keep-aliv...0yuvakt3v', 'Content-Length': '5211', 'Content-Type': 'multipart/form-data; boundary=fdef6c7d2e08eb882ed011200b3e56b5'}
retries = Retry(total=0, connect=None, read=False, redirect=None, status=None), redirect = False, assert_same_host = False, timeout = Timeout(connect=None, read=None, total=None), pool_timeout = None
release_conn = False, chunked = False, body_pos = None, preload_content = False, decode_content = False, response_kw = {}
parsed_url = Url(scheme=None, auth=None, host=None, port=None, path='/api/v5/addons/upload/', query=None, fragment=None), destination_scheme = None, conn = None, release_this_conn = True
http_tunnel_required = False, err = None, clean_exit = False

def urlopen( # type: ignore[override]
self,
method: str,
url: str,
body: _TYPE_BODY | None = None,
headers: typing.Mapping[str, str] | None = None,
retries: Retry | bool | int | None = None,
redirect: bool = True,
assert_same_host: bool = True,
timeout: _TYPE_TIMEOUT = _DEFAULT_TIMEOUT,
pool_timeout: int | None = None,
release_conn: bool | None = None,
chunked: bool = False,
body_pos: _TYPE_BODY_POSITION | None = None,
preload_content: bool = True,
decode_content: bool = True,
**response_kw: typing.Any,
) -> BaseHTTPResponse:
"""
Get a connection from the pool and perform an HTTP request. This is the
lowest level call for making a request, so you'll need to specify all
the raw details.

.. note::

More commonly, it's appropriate to use a convenience method
such as :meth:`request`.

.. note::

`release_conn` will only behave as expected if
`preload_content=False` because we want to make
`preload_content=False` the default behaviour someday soon without
breaking backwards compatibility.

:param method:
HTTP request method (such as GET, POST, PUT, etc.)

:param url:
The URL to perform the request on.

:param body:
Data to send in the request body, either :class:`str`, :class:`bytes`,
an iterable of :class:`str`/:class:`bytes`, or a file-like object.

:param headers:
Dictionary of custom headers to send, such as User-Agent,
If-None-Match, etc. If None, pool headers are used. If provided,
these headers completely replace any pool-specific headers.

:param retries:
Configure the number of retries to allow before raising a
:class:`~urllib3.exceptions.MaxRetryError` exception.

If ``None`` (default) will retry 3 times, see ``Retry.DEFAULT``. Pass a
:class:`~urllib3.util.retry.Retry` object for fine-grained control
over different types of retries.
Pass an integer number to retry connection errors that many times,
but no other types of errors. Pass zero to never retry.

If ``False``, then retries are disabled and any exception is raised
immediately. Also, instead of raising a MaxRetryError on redirects,
the redirect response will be returned.

:type retries: :class:`~urllib3.util.retry.Retry`, False, or an int.

:param redirect:
If True, automatically handle redirects (status codes 301, 302,
303, 307, 308). Each redirect counts as a retry. Disabling retries
will disable redirect, too.

:param assert_same_host:
If ``True``, will make sure that the host of the pool requests is
consistent else will raise HostChangedError. When ``False``, you can
use the pool on an HTTP proxy and request foreign hosts.

:param timeout:
If specified, overrides the default timeout for this one
request. It may be a float (in seconds) or an instance of
:class:`urllib3.util.Timeout`.

:param pool_timeout:
If set and the pool is set to block=True, then this method will
block for ``pool_timeout`` seconds and raise EmptyPoolError if no
connection is available within the time period.

:param bool preload_content:
If True, the response's body will be preloaded into memory.

:param bool decode_content:
If True, will attempt to decode the body based on the
'content-encoding' header.

:param release_conn:
If False, then the urlopen call will not release the connection
back into the pool once a response is received (but will release if
you read the entire contents of the response such as when
`preload_content=True`). This is useful if you're not preloading
the response's content immediately. You will need to call
``r.release_conn()`` on the response ``r`` to return the connection
back into the pool. If None, it takes the value of ``preload_content``
which defaults to ``True``.

:param bool chunked:
If True, urllib3 will send the body using chunked transfer
encoding. Otherwise, urllib3 will send the body using the standard
content-length form. Defaults to False.

:param int body_pos:
Position to seek to in file-like body in the event of a retry or
redirect. Typically this won't need to be set because urllib3 will
auto-populate the value when needed.
"""
parsed_url = parse_url(url)
destination_scheme = parsed_url.scheme

if headers is None:
headers = self.headers

if not isinstance(retries, Retry):
retries = Retry.from_int(retries, redirect=redirect, default=self.retries)

if release_conn is None:
release_conn = preload_content

# Check host
if assert_same_host and not self.is_same_host(url):
raise HostChangedError(self, url, retries)

# Ensure that the URL we're connecting to is properly encoded
if url.startswith("/"):
url = to_str(_encode_target(url))
else:
url = to_str(parsed_url.url)

conn = None

# Track whether `conn` needs to be released before
# returning/raising/recursing. Update this variable if necessary, and
# leave `release_conn` constant throughout the function. That way, if
# the function recurses, the original value of `release_conn` will be
# passed down into the recursive call, and its value will be respected.
#
# See issue #651 [1] for details.
#
# [1] <https://github.com/urllib3/urllib3/issues/651>
release_this_conn = release_conn

http_tunnel_required = connection_requires_http_tunnel(
self.proxy, self.proxy_config, destination_scheme
)

# Merge the proxy headers. Only done when not using HTTP CONNECT. We
# have to copy the headers dict so we can safely change it without those
# changes being reflected in anyone else's copy.
if not http_tunnel_required:
headers = headers.copy() # type: ignore[attr-defined]
headers.update(self.proxy_headers) # type: ignore[union-attr]

# Must keep the exception bound to a separate variable or else Python 3
# complains about UnboundLocalError.
err = None

# Keep track of whether we cleanly exited the except block. This
# ensures we do proper cleanup in finally.
clean_exit = False

# Rewind body position, if needed. Record current position
# for future rewinds in the event of a redirect/retry.
body_pos = set_file_position(body, body_pos)

try:
# Request a connection from the queue.
timeout_obj = self._get_timeout(timeout)
conn = self._get_conn(timeout=pool_timeout)

conn.timeout = timeout_obj.connect_timeout # type: ignore[assignment]

# Is this a closed/new connection that requires CONNECT tunnelling?
if self.proxy is not None and http_tunnel_required and conn.is_closed:
try:
self._prepare_proxy(conn)
except (BaseSSLError, OSError, SocketTimeout) as e:
self._raise_timeout(
err=e, url=self.proxy.url, timeout_value=conn.timeout
)
raise

# If we're going to release the connection in ``finally:``, then
# the response doesn't need to know about the connection. Otherwise
# it will also try to release it and we'll have a double-release
# mess.
response_conn = conn if not release_conn else None

# Make the request on the HTTPConnection object
> response = self._make_request(
conn,
method,
url,
timeout=timeout_obj,
body=body,
headers=headers,
chunked=chunked,
retries=retries,
response_conn=response_conn,
preload_content=preload_content,
decode_content=decode_content,
**response_kw,
)

venv/lib/python3.11/site-packages/urllib3/connectionpool.py:789:
_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _
venv/lib/python3.11/site-packages/urllib3/connectionpool.py:490: in _make_request
raise new_e
venv/lib/python3.11/site-packages/urllib3/connectionpool.py:466: in _make_request
self._validate_conn(conn)
venv/lib/python3.11/site-packages/urllib3/connectionpool.py:1095: in _validate_conn
conn.connect()
venv/lib/python3.11/site-packages/urllib3/connection.py:615: in connect
self.sock = sock = self._new_conn()
_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _

self = <urllib3.connection.HTTPSConnection object at 0x1040cec90>

def _new_conn(self) -> socket.socket:
"""Establish a socket connection and set nodelay settings on it.

:return: New socket connection.
"""
try:
sock = connection.create_connection(
(self._dns_host, self.port),
self.timeout,
source_address=self.source_address,
socket_options=self.socket_options,
)
except socket.gaierror as e:
> raise NameResolutionError(self.host, self, e) from e
E urllib3.exceptions.NameResolutionError: <urllib3.connection.HTTPSConnection object at 0x1040cec90>: Failed to resolve 'addons.allizom.org' ([Errno 8] nodename nor servname provided, or not known)

venv/lib/python3.11/site-packages/urllib3/connection.py:203: NameResolutionError

The above exception was the direct cause of the following exception:

self = <requests.adapters.HTTPAdapter object at 0x1040cf810>, request = <PreparedRequest [POST]>, stream = False, timeout = Timeout(connect=None, read=None, total=None), verify = True, cert = None
proxies = OrderedDict()

def send(
self, request, stream=False, timeout=None, verify=True, cert=None, proxies=None
):
"""Sends PreparedRequest object. Returns Response object.

:param request: The :class:`PreparedRequest <PreparedRequest>` being sent.
:param stream: (optional) Whether to stream the request content.
:param timeout: (optional) How long to wait for the server to send
data before giving up, as a float, or a :ref:`(connect timeout,
read timeout) <timeouts>` tuple.
:type timeout: float or tuple or urllib3 Timeout object
:param verify: (optional) Either a boolean, in which case it controls whether
we verify the server's TLS certificate, or a string, in which case it
must be a path to a CA bundle to use
:param cert: (optional) Any user-provided SSL certificate to be trusted.
:param proxies: (optional) The proxies dictionary to apply to the request.
:rtype: requests.Response
"""

try:
conn = self._get_connection(request, verify, proxies=proxies, cert=cert)
except LocationValueError as e:
raise InvalidURL(e, request=request)

self.cert_verify(conn, request.url, verify, cert)
url = self.request_url(request, proxies)
self.add_headers(
request,
stream=stream,
timeout=timeout,
verify=verify,
cert=cert,
proxies=proxies,
)

chunked = not (request.body is None or "Content-Length" in request.headers)

if isinstance(timeout, tuple):
try:
connect, read = timeout
timeout = TimeoutSauce(connect=connect, read=read)
except ValueError:
raise ValueError(
f"Invalid timeout {timeout}. Pass a (connect, read) timeout tuple, "
f"or a single float to set both timeouts to the same value."
)
elif isinstance(timeout, TimeoutSauce):
pass
else:
timeout = TimeoutSauce(connect=timeout, read=timeout)

try:
> resp = conn.urlopen(
method=request.method,
url=url,
body=request.body,
headers=request.headers,
redirect=False,
assert_same_host=False,
preload_content=False,
decode_content=False,
retries=self.max_retries,
timeout=timeout,
chunked=chunked,
)

venv/lib/python3.11/site-packages/requests/adapters.py:564:
_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _
venv/lib/python3.11/site-packages/urllib3/connectionpool.py:843: in urlopen
retries = retries.increment(
_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _

self = Retry(total=0, connect=None, read=False, redirect=None, status=None), method = 'POST', url = '/api/v5/addons/upload/', response = None
error = NameResolutionError("<urllib3.connection.HTTPSConnection object at 0x1040cec90>: Failed to resolve 'addons.allizom.org' ([Errno 8] nodename nor servname provided, or not known)")
_pool = <urllib3.connectionpool.HTTPSConnectionPool object at 0x1040cc510>, _stacktrace = <traceback object at 0x1040cdf40>

def increment(
self,
method: str | None = None,
url: str | None = None,
response: BaseHTTPResponse | None = None,
error: Exception | None = None,
_pool: ConnectionPool | None = None,
_stacktrace: TracebackType | None = None,
) -> Self:
"""Return a new Retry object with incremented retry counters.

:param response: A response object, or None, if the server did not
return a response.
:type response: :class:`~urllib3.response.BaseHTTPResponse`
:param Exception error: An error encountered during the request, or
None if the response was received successfully.

:return: A new ``Retry`` object.
"""
if self.total is False and error:
# Disabled, indicate to re-raise the error.
raise reraise(type(error), error, _stacktrace)

total = self.total
if total is not None:
total -= 1

connect = self.connect
read = self.read
redirect = self.redirect
status_count = self.status
other = self.other
cause = "unknown"
status = None
redirect_location = None

if error and self._is_connection_error(error):
# Connect retry?
if connect is False:
raise reraise(type(error), error, _stacktrace)
elif connect is not None:
connect -= 1

elif error and self._is_read_error(error):
# Read retry?
if read is False or method is None or not self._is_method_retryable(method):
raise reraise(type(error), error, _stacktrace)
elif read is not None:
read -= 1

elif error:
# Other retry?
if other is not None:
other -= 1

elif response and response.get_redirect_location():
# Redirect retry?
if redirect is not None:
redirect -= 1
cause = "too many redirects"
response_redirect_location = response.get_redirect_location()
if response_redirect_location:
redirect_location = response_redirect_location
status = response.status

else:
# Incrementing because of a server error like a 500 in
# status_forcelist and the given method is in the allowed_methods
cause = ResponseError.GENERIC_ERROR
if response and response.status:
if status_count is not None:
status_count -= 1
cause = ResponseError.SPECIFIC_ERROR.format(status_code=response.status)
status = response.status

history = self.history + (
RequestHistory(method, url, error, status, redirect_location),
)

new_retry = self.new(
total=total,
connect=connect,
read=read,
redirect=redirect,
status=status_count,
other=other,
history=history,
)

if new_retry.is_exhausted():
reason = error or ResponseError(cause)
> raise MaxRetryError(_pool, url, reason) from reason # type: ignore[arg-type]
E urllib3.exceptions.MaxRetryError: HTTPSConnectionPool(host='addons.allizom.org', port=443): Max retries exceeded with url: /api/v5/addons/upload/ (Caused by NameResolutionError("<urllib3.connection.HTTPSConnection object at 0x1040cec90>: Failed to resolve 'addons.allizom.org' ([Errno 8] nodename nor servname provided, or not known)"))

venv/lib/python3.11/site-packages/urllib3/util/retry.py:519: MaxRetryError

During handling of the above exception, another exception occurred:

base_url = 'https://addons.allizom.org', session_auth = 'ldvd5ag27bkfpukx6rn2lcj0yuvakt3v'

@pytest.mark.serial
@pytest.mark.create_session("api_user")
def test_upload_privileged_addon_with_unauthorized_account(base_url, session_auth):
"""Upload an addon signed with a mozilla signature using an unauthorized account"""
with open("sample-addons/mozilla-signed.xpi", "rb") as file:
> upload = requests.post(
url=f"{base_url}{_upload}",
headers={"Authorization": f"Session {session_auth}"},
files={"upload": file},
data={"channel": "unlisted"},
)

tests/api_w/test_addon_uploads.py:1206:
_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _
venv/lib/python3.11/site-packages/requests/api.py:115: in post
return request("post", url, data=data, json=json, **kwargs)
venv/lib/python3.11/site-packages/requests/api.py:59: in request
return session.request(method=method, url=url, **kwargs)
venv/lib/python3.11/site-packages/requests/sessions.py:589: in request
resp = self.send(prep, **send_kwargs)
venv/lib/python3.11/site-packages/requests/sessions.py:703: in send
r = adapter.send(request, **kwargs)
_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _

self = <requests.adapters.HTTPAdapter object at 0x1040cf810>, request = <PreparedRequest [POST]>, stream = False, timeout = Timeout(connect=None, read=None, total=None), verify = True, cert = None
proxies = OrderedDict()

def send(
self, request, stream=False, timeout=None, verify=True, cert=None, proxies=None
):
"""Sends PreparedRequest object. Returns Response object.

:param request: The :class:`PreparedRequest <PreparedRequest>` being sent.
:param stream: (optional) Whether to stream the request content.
:param timeout: (optional) How long to wait for the server to send
data before giving up, as a float, or a :ref:`(connect timeout,
read timeout) <timeouts>` tuple.
:type timeout: float or tuple or urllib3 Timeout object
:param verify: (optional) Either a boolean, in which case it controls whether
we verify the server's TLS certificate, or a string, in which case it
must be a path to a CA bundle to use
:param cert: (optional) Any user-provided SSL certificate to be trusted.
:param proxies: (optional) The proxies dictionary to apply to the request.
:rtype: requests.Response
"""

try:
conn = self._get_connection(request, verify, proxies=proxies, cert=cert)
except LocationValueError as e:
raise InvalidURL(e, request=request)

self.cert_verify(conn, request.url, verify, cert)
url = self.request_url(request, proxies)
self.add_headers(
request,
stream=stream,
timeout=timeout,
verify=verify,
cert=cert,
proxies=proxies,
)

chunked = not (request.body is None or "Content-Length" in request.headers)

if isinstance(timeout, tuple):
try:
connect, read = timeout
timeout = TimeoutSauce(connect=connect, read=read)
except ValueError:
raise ValueError(
f"Invalid timeout {timeout}. Pass a (connect, read) timeout tuple, "
f"or a single float to set both timeouts to the same value."
)
elif isinstance(timeout, TimeoutSauce):
pass
else:
timeout = TimeoutSauce(connect=timeout, read=timeout)

try:
resp = conn.urlopen(
method=request.method,
url=url,
body=request.body,
headers=request.headers,
redirect=False,
assert_same_host=False,
preload_content=False,
decode_content=False,
retries=self.max_retries,
timeout=timeout,
chunked=chunked,
)

except (ProtocolError, OSError) as err:
raise ConnectionError(err, request=request)

except MaxRetryError as e:
if isinstance(e.reason, ConnectTimeoutError):
# TODO: Remove this in 3.0.0: see #2811
if not isinstance(e.reason, NewConnectionError):
raise ConnectTimeout(e, request=request)

if isinstance(e.reason, ResponseError):
raise RetryError(e, request=request)

if isinstance(e.reason, _ProxyError):
raise ProxyError(e, request=request)

if isinstance(e.reason, _SSLError):
# This branch is for urllib3 v1.22 and later.
raise SSLError(e, request=request)

> raise ConnectionError(e, request=request)
E requests.exceptions.ConnectionError: HTTPSConnectionPool(host='addons.allizom.org', port=443): Max retries exceeded with url: /api/v5/addons/upload/ (Caused by NameResolutionError("<urllib3.connection.HTTPSConnection object at 0x1040cec90>: Failed to resolve 'addons.allizom.org' ([Errno 8] nodename nor servname provided, or not known)"))

venv/lib/python3.11/site-packages/requests/adapters.py:597: ConnectionError
Failed tests/api_w/test_addon_uploads.py::test_upload_addon_with_reserved_guid_authorized_account 0.00
self = <urllib3.connection.HTTPSConnection object at 0x1040441d0>

def _new_conn(self) -> socket.socket:
"""Establish a socket connection and set nodelay settings on it.

:return: New socket connection.
"""
try:
> sock = connection.create_connection(
(self._dns_host, self.port),
self.timeout,
source_address=self.source_address,
socket_options=self.socket_options,
)

venv/lib/python3.11/site-packages/urllib3/connection.py:196:
_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _
venv/lib/python3.11/site-packages/urllib3/util/connection.py:60: in create_connection
for res in socket.getaddrinfo(host, port, family, socket.SOCK_STREAM):
_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _

host = 'addons.allizom.org', port = 443, family = <AddressFamily.AF_UNSPEC: 0>, type = <SocketKind.SOCK_STREAM: 1>, proto = 0, flags = 0

def getaddrinfo(host, port, family=0, type=0, proto=0, flags=0):
"""Resolve host and port into list of address info entries.

Translate the host/port argument into a sequence of 5-tuples that contain
all the necessary arguments for creating a socket connected to that service.
host is a domain name, a string representation of an IPv4/v6 address or
None. port is a string service name such as 'http', a numeric port number or
None. By passing None as the value of host and port, you can pass NULL to
the underlying C API.

The family, type and proto arguments can be optionally specified in order to
narrow the list of addresses returned. Passing zero as a value for each of
these arguments selects the full range of results.
"""
# We override this function since we want to translate the numeric family
# and socket type values to enum constants.
addrlist = []
> for res in _socket.getaddrinfo(host, port, family, type, proto, flags):
E socket.gaierror: [Errno 8] nodename nor servname provided, or not known

/Library/Frameworks/Python.framework/Versions/3.11/lib/python3.11/socket.py:962: gaierror

The above exception was the direct cause of the following exception:

self = <urllib3.connectionpool.HTTPSConnectionPool object at 0x104045450>, method = 'POST', url = '/api/v5/addons/upload/'
body = b'--f6d11af992ddb74ffc6615fe13f2686c\r\nContent-Disposition: form-data; name="channel"\r\n\r\nunlisted\r\n--f6d11af992...5\x06\x00\x00\x00\x00\x01\x00\x01\x00;\x00\x00\x00\xb7\x00\x00\x00\x00\x00\r\n--f6d11af992ddb74ffc6615fe13f2686c--\r\n'
headers = {'User-Agent': 'python-requests/2.32.0', 'Accept-Encoding': 'gzip, deflate', 'Accept': '*/*', 'Connection': 'keep-aliv...l8biyyxblf', 'Content-Length': '512', 'Content-Type': 'multipart/form-data; boundary=f6d11af992ddb74ffc6615fe13f2686c'}
retries = Retry(total=0, connect=None, read=False, redirect=None, status=None), redirect = False, assert_same_host = False, timeout = Timeout(connect=None, read=None, total=None), pool_timeout = None
release_conn = False, chunked = False, body_pos = None, preload_content = False, decode_content = False, response_kw = {}
parsed_url = Url(scheme=None, auth=None, host=None, port=None, path='/api/v5/addons/upload/', query=None, fragment=None), destination_scheme = None, conn = None, release_this_conn = True
http_tunnel_required = False, err = None, clean_exit = False

def urlopen( # type: ignore[override]
self,
method: str,
url: str,
body: _TYPE_BODY | None = None,
headers: typing.Mapping[str, str] | None = None,
retries: Retry | bool | int | None = None,
redirect: bool = True,
assert_same_host: bool = True,
timeout: _TYPE_TIMEOUT = _DEFAULT_TIMEOUT,
pool_timeout: int | None = None,
release_conn: bool | None = None,
chunked: bool = False,
body_pos: _TYPE_BODY_POSITION | None = None,
preload_content: bool = True,
decode_content: bool = True,
**response_kw: typing.Any,
) -> BaseHTTPResponse:
"""
Get a connection from the pool and perform an HTTP request. This is the
lowest level call for making a request, so you'll need to specify all
the raw details.

.. note::

More commonly, it's appropriate to use a convenience method
such as :meth:`request`.

.. note::

`release_conn` will only behave as expected if
`preload_content=False` because we want to make
`preload_content=False` the default behaviour someday soon without
breaking backwards compatibility.

:param method:
HTTP request method (such as GET, POST, PUT, etc.)

:param url:
The URL to perform the request on.

:param body:
Data to send in the request body, either :class:`str`, :class:`bytes`,
an iterable of :class:`str`/:class:`bytes`, or a file-like object.

:param headers:
Dictionary of custom headers to send, such as User-Agent,
If-None-Match, etc. If None, pool headers are used. If provided,
these headers completely replace any pool-specific headers.

:param retries:
Configure the number of retries to allow before raising a
:class:`~urllib3.exceptions.MaxRetryError` exception.

If ``None`` (default) will retry 3 times, see ``Retry.DEFAULT``. Pass a
:class:`~urllib3.util.retry.Retry` object for fine-grained control
over different types of retries.
Pass an integer number to retry connection errors that many times,
but no other types of errors. Pass zero to never retry.

If ``False``, then retries are disabled and any exception is raised
immediately. Also, instead of raising a MaxRetryError on redirects,
the redirect response will be returned.

:type retries: :class:`~urllib3.util.retry.Retry`, False, or an int.

:param redirect:
If True, automatically handle redirects (status codes 301, 302,
303, 307, 308). Each redirect counts as a retry. Disabling retries
will disable redirect, too.

:param assert_same_host:
If ``True``, will make sure that the host of the pool requests is
consistent else will raise HostChangedError. When ``False``, you can
use the pool on an HTTP proxy and request foreign hosts.

:param timeout:
If specified, overrides the default timeout for this one
request. It may be a float (in seconds) or an instance of
:class:`urllib3.util.Timeout`.

:param pool_timeout:
If set and the pool is set to block=True, then this method will
block for ``pool_timeout`` seconds and raise EmptyPoolError if no
connection is available within the time period.

:param bool preload_content:
If True, the response's body will be preloaded into memory.

:param bool decode_content:
If True, will attempt to decode the body based on the
'content-encoding' header.

:param release_conn:
If False, then the urlopen call will not release the connection
back into the pool once a response is received (but will release if
you read the entire contents of the response such as when
`preload_content=True`). This is useful if you're not preloading
the response's content immediately. You will need to call
``r.release_conn()`` on the response ``r`` to return the connection
back into the pool. If None, it takes the value of ``preload_content``
which defaults to ``True``.

:param bool chunked:
If True, urllib3 will send the body using chunked transfer
encoding. Otherwise, urllib3 will send the body using the standard
content-length form. Defaults to False.

:param int body_pos:
Position to seek to in file-like body in the event of a retry or
redirect. Typically this won't need to be set because urllib3 will
auto-populate the value when needed.
"""
parsed_url = parse_url(url)
destination_scheme = parsed_url.scheme

if headers is None:
headers = self.headers

if not isinstance(retries, Retry):
retries = Retry.from_int(retries, redirect=redirect, default=self.retries)

if release_conn is None:
release_conn = preload_content

# Check host
if assert_same_host and not self.is_same_host(url):
raise HostChangedError(self, url, retries)

# Ensure that the URL we're connecting to is properly encoded
if url.startswith("/"):
url = to_str(_encode_target(url))
else:
url = to_str(parsed_url.url)

conn = None

# Track whether `conn` needs to be released before
# returning/raising/recursing. Update this variable if necessary, and
# leave `release_conn` constant throughout the function. That way, if
# the function recurses, the original value of `release_conn` will be
# passed down into the recursive call, and its value will be respected.
#
# See issue #651 [1] for details.
#
# [1] <https://github.com/urllib3/urllib3/issues/651>
release_this_conn = release_conn

http_tunnel_required = connection_requires_http_tunnel(
self.proxy, self.proxy_config, destination_scheme
)

# Merge the proxy headers. Only done when not using HTTP CONNECT. We
# have to copy the headers dict so we can safely change it without those
# changes being reflected in anyone else's copy.
if not http_tunnel_required:
headers = headers.copy() # type: ignore[attr-defined]
headers.update(self.proxy_headers) # type: ignore[union-attr]

# Must keep the exception bound to a separate variable or else Python 3
# complains about UnboundLocalError.
err = None

# Keep track of whether we cleanly exited the except block. This
# ensures we do proper cleanup in finally.
clean_exit = False

# Rewind body position, if needed. Record current position
# for future rewinds in the event of a redirect/retry.
body_pos = set_file_position(body, body_pos)

try:
# Request a connection from the queue.
timeout_obj = self._get_timeout(timeout)
conn = self._get_conn(timeout=pool_timeout)

conn.timeout = timeout_obj.connect_timeout # type: ignore[assignment]

# Is this a closed/new connection that requires CONNECT tunnelling?
if self.proxy is not None and http_tunnel_required and conn.is_closed:
try:
self._prepare_proxy(conn)
except (BaseSSLError, OSError, SocketTimeout) as e:
self._raise_timeout(
err=e, url=self.proxy.url, timeout_value=conn.timeout
)
raise

# If we're going to release the connection in ``finally:``, then
# the response doesn't need to know about the connection. Otherwise
# it will also try to release it and we'll have a double-release
# mess.
response_conn = conn if not release_conn else None

# Make the request on the HTTPConnection object
> response = self._make_request(
conn,
method,
url,
timeout=timeout_obj,
body=body,
headers=headers,
chunked=chunked,
retries=retries,
response_conn=response_conn,
preload_content=preload_content,
decode_content=decode_content,
**response_kw,
)

venv/lib/python3.11/site-packages/urllib3/connectionpool.py:789:
_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _
venv/lib/python3.11/site-packages/urllib3/connectionpool.py:490: in _make_request
raise new_e
venv/lib/python3.11/site-packages/urllib3/connectionpool.py:466: in _make_request
self._validate_conn(conn)
venv/lib/python3.11/site-packages/urllib3/connectionpool.py:1095: in _validate_conn
conn.connect()
venv/lib/python3.11/site-packages/urllib3/connection.py:615: in connect
self.sock = sock = self._new_conn()
_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _

self = <urllib3.connection.HTTPSConnection object at 0x1040441d0>

def _new_conn(self) -> socket.socket:
"""Establish a socket connection and set nodelay settings on it.

:return: New socket connection.
"""
try:
sock = connection.create_connection(
(self._dns_host, self.port),
self.timeout,
source_address=self.source_address,
socket_options=self.socket_options,
)
except socket.gaierror as e:
> raise NameResolutionError(self.host, self, e) from e
E urllib3.exceptions.NameResolutionError: <urllib3.connection.HTTPSConnection object at 0x1040441d0>: Failed to resolve 'addons.allizom.org' ([Errno 8] nodename nor servname provided, or not known)

venv/lib/python3.11/site-packages/urllib3/connection.py:203: NameResolutionError

The above exception was the direct cause of the following exception:

self = <requests.adapters.HTTPAdapter object at 0x1040460d0>, request = <PreparedRequest [POST]>, stream = False, timeout = Timeout(connect=None, read=None, total=None), verify = True, cert = None
proxies = OrderedDict()

def send(
self, request, stream=False, timeout=None, verify=True, cert=None, proxies=None
):
"""Sends PreparedRequest object. Returns Response object.

:param request: The :class:`PreparedRequest <PreparedRequest>` being sent.
:param stream: (optional) Whether to stream the request content.
:param timeout: (optional) How long to wait for the server to send
data before giving up, as a float, or a :ref:`(connect timeout,
read timeout) <timeouts>` tuple.
:type timeout: float or tuple or urllib3 Timeout object
:param verify: (optional) Either a boolean, in which case it controls whether
we verify the server's TLS certificate, or a string, in which case it
must be a path to a CA bundle to use
:param cert: (optional) Any user-provided SSL certificate to be trusted.
:param proxies: (optional) The proxies dictionary to apply to the request.
:rtype: requests.Response
"""

try:
conn = self._get_connection(request, verify, proxies=proxies, cert=cert)
except LocationValueError as e:
raise InvalidURL(e, request=request)

self.cert_verify(conn, request.url, verify, cert)
url = self.request_url(request, proxies)
self.add_headers(
request,
stream=stream,
timeout=timeout,
verify=verify,
cert=cert,
proxies=proxies,
)

chunked = not (request.body is None or "Content-Length" in request.headers)

if isinstance(timeout, tuple):
try:
connect, read = timeout
timeout = TimeoutSauce(connect=connect, read=read)
except ValueError:
raise ValueError(
f"Invalid timeout {timeout}. Pass a (connect, read) timeout tuple, "
f"or a single float to set both timeouts to the same value."
)
elif isinstance(timeout, TimeoutSauce):
pass
else:
timeout = TimeoutSauce(connect=timeout, read=timeout)

try:
> resp = conn.urlopen(
method=request.method,
url=url,
body=request.body,
headers=request.headers,
redirect=False,
assert_same_host=False,
preload_content=False,
decode_content=False,
retries=self.max_retries,
timeout=timeout,
chunked=chunked,
)

venv/lib/python3.11/site-packages/requests/adapters.py:564:
_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _
venv/lib/python3.11/site-packages/urllib3/connectionpool.py:843: in urlopen
retries = retries.increment(
_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _

self = Retry(total=0, connect=None, read=False, redirect=None, status=None), method = 'POST', url = '/api/v5/addons/upload/', response = None
error = NameResolutionError("<urllib3.connection.HTTPSConnection object at 0x1040441d0>: Failed to resolve 'addons.allizom.org' ([Errno 8] nodename nor servname provided, or not known)")
_pool = <urllib3.connectionpool.HTTPSConnectionPool object at 0x104045450>, _stacktrace = <traceback object at 0x104047ec0>

def increment(
self,
method: str | None = None,
url: str | None = None,
response: BaseHTTPResponse | None = None,
error: Exception | None = None,
_pool: ConnectionPool | None = None,
_stacktrace: TracebackType | None = None,
) -> Self:
"""Return a new Retry object with incremented retry counters.

:param response: A response object, or None, if the server did not
return a response.
:type response: :class:`~urllib3.response.BaseHTTPResponse`
:param Exception error: An error encountered during the request, or
None if the response was received successfully.

:return: A new ``Retry`` object.
"""
if self.total is False and error:
# Disabled, indicate to re-raise the error.
raise reraise(type(error), error, _stacktrace)

total = self.total
if total is not None:
total -= 1

connect = self.connect
read = self.read
redirect = self.redirect
status_count = self.status
other = self.other
cause = "unknown"
status = None
redirect_location = None

if error and self._is_connection_error(error):
# Connect retry?
if connect is False:
raise reraise(type(error), error, _stacktrace)
elif connect is not None:
connect -= 1

elif error and self._is_read_error(error):
# Read retry?
if read is False or method is None or not self._is_method_retryable(method):
raise reraise(type(error), error, _stacktrace)
elif read is not None:
read -= 1

elif error:
# Other retry?
if other is not None:
other -= 1

elif response and response.get_redirect_location():
# Redirect retry?
if redirect is not None:
redirect -= 1
cause = "too many redirects"
response_redirect_location = response.get_redirect_location()
if response_redirect_location:
redirect_location = response_redirect_location
status = response.status

else:
# Incrementing because of a server error like a 500 in
# status_forcelist and the given method is in the allowed_methods
cause = ResponseError.GENERIC_ERROR
if response and response.status:
if status_count is not None:
status_count -= 1
cause = ResponseError.SPECIFIC_ERROR.format(status_code=response.status)
status = response.status

history = self.history + (
RequestHistory(method, url, error, status, redirect_location),
)

new_retry = self.new(
total=total,
connect=connect,
read=read,
redirect=redirect,
status=status_count,
other=other,
history=history,
)

if new_retry.is_exhausted():
reason = error or ResponseError(cause)
> raise MaxRetryError(_pool, url, reason) from reason # type: ignore[arg-type]
E urllib3.exceptions.MaxRetryError: HTTPSConnectionPool(host='addons.allizom.org', port=443): Max retries exceeded with url: /api/v5/addons/upload/ (Caused by NameResolutionError("<urllib3.connection.HTTPSConnection object at 0x1040441d0>: Failed to resolve 'addons.allizom.org' ([Errno 8] nodename nor servname provided, or not known)"))

venv/lib/python3.11/site-packages/urllib3/util/retry.py:519: MaxRetryError

During handling of the above exception, another exception occurred:

base_url = 'https://addons.allizom.org', session_auth = 'km4duy1yzlp6bduifqwjbrl8biyyxblf'

@pytest.mark.serial
@pytest.mark.create_session("staff_user")
def test_upload_addon_with_reserved_guid_authorized_account(base_url, session_auth):
"""Upload an addon with a reserved guid using an account that holds the right permissions"""
# create a restricted GUID
guid = f"{reusables.get_random_string(10)}@mozilla.org"
manifest = {
**payloads.minimal_manifest,
"name": "Reserved guid",
"browser_specific_settings": {"gecko": {"id": guid}},
}
api_helpers.make_addon(manifest)
with open("sample-addons/make-addon.zip", "rb") as file:
> upload = requests.post(
url=f"{base_url}{_upload}",
headers={"Authorization": f"Session {session_auth}"},
files={"upload": file},
data={"channel": "unlisted"},
)

tests/api_w/test_addon_uploads.py:1281:
_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _
venv/lib/python3.11/site-packages/requests/api.py:115: in post
return request("post", url, data=data, json=json, **kwargs)
venv/lib/python3.11/site-packages/requests/api.py:59: in request
return session.request(method=method, url=url, **kwargs)
venv/lib/python3.11/site-packages/requests/sessions.py:589: in request
resp = self.send(prep, **send_kwargs)
venv/lib/python3.11/site-packages/requests/sessions.py:703: in send
r = adapter.send(request, **kwargs)
_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _

self = <requests.adapters.HTTPAdapter object at 0x1040460d0>, request = <PreparedRequest [POST]>, stream = False, timeout = Timeout(connect=None, read=None, total=None), verify = True, cert = None
proxies = OrderedDict()

def send(
self, request, stream=False, timeout=None, verify=True, cert=None, proxies=None
):
"""Sends PreparedRequest object. Returns Response object.

:param request: The :class:`PreparedRequest <PreparedRequest>` being sent.
:param stream: (optional) Whether to stream the request content.
:param timeout: (optional) How long to wait for the server to send
data before giving up, as a float, or a :ref:`(connect timeout,
read timeout) <timeouts>` tuple.
:type timeout: float or tuple or urllib3 Timeout object
:param verify: (optional) Either a boolean, in which case it controls whether
we verify the server's TLS certificate, or a string, in which case it
must be a path to a CA bundle to use
:param cert: (optional) Any user-provided SSL certificate to be trusted.
:param proxies: (optional) The proxies dictionary to apply to the request.
:rtype: requests.Response
"""

try:
conn = self._get_connection(request, verify, proxies=proxies, cert=cert)
except LocationValueError as e:
raise InvalidURL(e, request=request)

self.cert_verify(conn, request.url, verify, cert)
url = self.request_url(request, proxies)
self.add_headers(
request,
stream=stream,
timeout=timeout,
verify=verify,
cert=cert,
proxies=proxies,
)

chunked = not (request.body is None or "Content-Length" in request.headers)

if isinstance(timeout, tuple):
try:
connect, read = timeout
timeout = TimeoutSauce(connect=connect, read=read)
except ValueError:
raise ValueError(
f"Invalid timeout {timeout}. Pass a (connect, read) timeout tuple, "
f"or a single float to set both timeouts to the same value."
)
elif isinstance(timeout, TimeoutSauce):
pass
else:
timeout = TimeoutSauce(connect=timeout, read=timeout)

try:
resp = conn.urlopen(
method=request.method,
url=url,
body=request.body,
headers=request.headers,
redirect=False,
assert_same_host=False,
preload_content=False,
decode_content=False,
retries=self.max_retries,
timeout=timeout,
chunked=chunked,
)

except (ProtocolError, OSError) as err:
raise ConnectionError(err, request=request)

except MaxRetryError as e:
if isinstance(e.reason, ConnectTimeoutError):
# TODO: Remove this in 3.0.0: see #2811
if not isinstance(e.reason, NewConnectionError):
raise ConnectTimeout(e, request=request)

if isinstance(e.reason, ResponseError):
raise RetryError(e, request=request)

if isinstance(e.reason, _ProxyError):
raise ProxyError(e, request=request)

if isinstance(e.reason, _SSLError):
# This branch is for urllib3 v1.22 and later.
raise SSLError(e, request=request)

> raise ConnectionError(e, request=request)
E requests.exceptions.ConnectionError: HTTPSConnectionPool(host='addons.allizom.org', port=443): Max retries exceeded with url: /api/v5/addons/upload/ (Caused by NameResolutionError("<urllib3.connection.HTTPSConnection object at 0x1040441d0>: Failed to resolve 'addons.allizom.org' ([Errno 8] nodename nor servname provided, or not known)"))

venv/lib/python3.11/site-packages/requests/adapters.py:597: ConnectionError
------------------------------Captured stdout call------------------------------
Manifest content: {'manifest_version': 2, 'version': '1.0', 'name': 'Reserved guid', 'browser_specific_settings': {'gecko': {'id': 'ksojvpvgng@mozilla.org'}}}
Skipped tests/api_w/test_addon_abuse_report.py::test_abuse_report_unauthenticated_post[Desktop] 0.00
('/Users/alexandru.schek/addons-release-tests/tests/api_w/test_addon_abuse_report.py', 12, 'Skipped: Skipped for the moment due to throttle in place, to be removed with next pr')
Skipped tests/api_w/test_addon_uploads.py::test_upload_addon_restricted_user[Desktop] 0.00
('/Users/alexandru.schek/addons-release-tests/tests/api_w/test_addon_uploads.py', 1346, 'Skipped: skip, need to update the user')
Passed tests/api_w/test_addon_abuse_report.py::test_abuse_report_authenticated[Desktop] 85.24
-----------------------------Captured stdout setup------------------------------
The "click continue button" event occurred.
Passed tests/api_w/test_addon_abuse_report.py::test_abuse_report_minimal_details[Desktop] 6.41
No log output captured.
Passed tests/api_w/test_addon_abuse_report.py::test_addon_install_method_parameter[Desktop-Accepted value: link] 6.29
No log output captured.
Passed tests/api_w/test_addon_abuse_report.py::test_addon_install_method_parameter[Desktop-Unsupported value: random_text] 6.16
No log output captured.
Passed tests/api_w/test_addon_abuse_report.py::test_addon_install_source_parameter[Desktop-Accepted value: amo] 5.77
No log output captured.
Passed tests/api_w/test_addon_abuse_report.py::test_addon_install_source_parameter[Desktop-Unsupported value: random_text] 6.09
No log output captured.
Passed tests/api_w/test_addon_abuse_report.py::test_reason_parameter[Desktop-Accepted value: damage] 6.30
No log output captured.
Passed tests/api_w/test_addon_abuse_report.py::test_reason_parameter[Desktop-Unsupported value: random_text] 6.69
No log output captured.
Passed tests/api_w/test_addon_abuse_report.py::test_addon_signature_parameter[Desktop-Accepted value: curated_and_partner] 6.69
No log output captured.
Passed tests/api_w/test_addon_abuse_report.py::test_addon_signature_parameter[Desktop-Unsupported value: random_text] 6.45
No log output captured.
Passed tests/api_w/test_addon_abuse_report.py::test_report_entry_point_parameter[Desktop-Accepted value: unified_context_menu] 8.40
No log output captured.
Passed tests/api_w/test_addon_abuse_report.py::test_report_entry_point_parameter[Desktop-Unsupported value: random_text] 5.86
No log output captured.
Passed tests/api_w/test_addon_abuse_report.py::test_location_parameter[Desktop-Accepted value: both] 5.93
No log output captured.
Passed tests/api_w/test_addon_abuse_report.py::test_location_parameter[Desktop-Unsupported value: random_text] 5.93
No log output captured.
Passed tests/api_w/test_addon_uploads.py::test_unauthenticated_addon_upload 0.56
No log output captured.
Passed tests/api_w/test_addon_uploads.py::test_upload_addon_without_dev_agreement[Desktop] 48.08
------------------------------Captured stdout call------------------------------
The "click continue button" event occurred.
Passed tests/api_w/test_addon_uploads.py::test_bad_authentication_addon_upload[Desktop] 80.66
-----------------------------Captured stdout setup------------------------------
The "click continue button" event occurred.
------------------------------Captured stdout call------------------------------
Session Token: None Uploading to: https://addons.allizom.org/api/v5/addons/upload/
Passed tests/api_w/test_addon_uploads.py::test_upload_addon_unsupported_file_types[Archive in "7z" format] 10.13
No log output captured.
Passed tests/api_w/test_addon_uploads.py::test_upload_addon_unsupported_file_types[Archive in "tgz" format] 9.39
No log output captured.
Passed tests/api_w/test_addon_uploads.py::test_upload_addon_unsupported_file_types[Archive in "tar.gz" format] 11.25
No log output captured.
Passed tests/api_w/test_addon_uploads.py::test_upload_addon_unsupported_file_types[Non archive - JSON file] 10.36
No log output captured.